Wifi Synchronized Lamps
A project for someone who lights up your life...
2 years ago, as a Christmas present for a long-distance friend, I created lamps that would synchronize animations via internet connection. This year, 2 years later, I created this updated version with the knowledge gained from the additional years of electronics dabbling. This version is much simpler, without any external monitors or keyboards needed (and just one simple chip, not two!) in addition to an easy phone app interface (thanks to Blynk IoT) instead of website and physical soft potentiometer.
There are buttons in the app that provide more flexibility in what animations you want to add: there are 3 sliders for RGB control, in addition to a widget at the bottom that allows you to pick colors from a map (so you don't have to figure out what the RGB numbers are for the color you want). There are also preset buttons for happy, angry, sad, and "meh" so you can easily convey your emotions to the other person in the form of lamp animations, for the times you have something you want to talk about but don't want to bother the person with lots of texts.
No electronics experience? No worries! There are just 3 main steps: connecting the hardware, uploading the code, and creating the Blynk app. Do remember, however: what can go wrong, will go wrong. Always add plenty of time for debugging.
If you use exactly what I did and upload exactly what I have, you should be fine even if you've never worked with electronics. Even if you make adjustments to the project, reading through this tutorial should give you a sense of what you need to change if you use this as a guide. Cost was also kept as low as possible: total cost, if you have absolutely none of the components, is ~$40 max per lamp.
Materials
These are the materials you need for ONE lamp (multiply by the number of lamps you'd like to make):
- 1x NodeMCU ESP8266 chips ($7 each, $13 for 2)
- 1x protoboard or breadboards (~$1 each)
- soldering iron and solder
- 1x neopixel rings ($10 each, $8 if you buy from adafruit.com)
- 1x 5V power supply (at least 500mA output, so 1A or 2A will be perfect) with microUSB connection (or barrel jack but buy a barrel jack converter to bare wires) ($8 each)
- Not strictly necessary but HIGHLY recommended for circuit protection (few cents each, but you might have to buy in bulk)
- 1x 300-500Ohm resistor (I used 200Ohm and got away with it though)
- 1x 100-1000uF capacitor
- electrical wire (or you get get these ribbon types) (single core is best) (a few cents for 5")
- You don't need that much wire; just 5" will be enough
- You can do whatever you want for the exterior lamp (above are parts just for the electronics). I went with laser cut wood and acrylic, with sketchbook paper for light diffusion.
I attached Amazon links above for the cheapest options I could find (as of Dec 20, 2018), but you can definitely find components cheaper from different places. I'm still a university student so I had access to capacitors and resistors: try asking around any friends who work with electronics. Neopixels can be bought from adafruit.com for cheaper if you have other things you want to order from there (to save on shipping cost..). You can get the resistors and capacitors from DigiKey or Mouser too for much cheaper, though shipping may be higher. For the power supplies, an old phone charger will be fine (or just the microUSB cable if you want to plug the lamp into a USB port instead of wall outlet). If you have absolutely none of these components, your cost will be max ~$40 per lamp (and less per lamp the more you make, since you'll usually buy these components in bulk: protoboard can come in packs of 5 for example). I had things lying around so it was just $5 for me (yes, I'm a hoarder with friends who happen to let go of many things -- plus I reused neopixel rings from last time).
Arduino code and Adobe Illustrator files (for the laser cut box) are attached below.
Overview: How the Lamps Work
Alright, so once you have the materials, you might be wondering how they all come together. Here's an explanation:
The NodeMCU ESP8266 is a microcontroller that operates on 3.3V logic (as opposed to 5V logic like most Arduinos). It includes an onboard wifi chip and GPIO pins for using digital and analog signals with components you connect. You'll be using one of the pins capable of outputting PWM signals (see pinout here: any pin with the ~ next to it can generate the analog signals as opposed to digital signals of just 0 or 1, LOW or HIGH) to control the neopixel ring. For programming it, you can do this easily through the Arduino IDE, easily downloadable here. (note, I provided the Adafruit guide to their ESP8266 HUZZAH instead of the NodeMCE one we have. The guide is still applicable for both boards, but you'll just have to select a different board for uploading in Arduino.)
The neopixel ring is what creates the colored animations of the lamp. It has addressable LEDs in the ring formation, each of which can be individually controlled. It normally runs using 5V logic, which usually requires level shifting (explained here), but luckily the Adafruit neopixel library has been updated to support the ESP8266. While 5V components don't respond as reliably to 3.3V signals, it works fairly reliably when the neopixel is powered at a lower voltage (so 3.3V instead of 5V). See details on this here.
In terms of the connection from the microcontroller to the neopixel, it's safest to put a 300-500 Ohm resistor between the data line of the neopixel and the GPIO pin you'll send signals from (to protect the LEDs from any sudden surges). You should also add a 1000uF capacitor connected in parallel to the neopixel ring's power and ground wires: this is to provide protection from sudden surges in current. Read this for more best practices on using these LED rings (and here for the full user guide by Adafruit).
For interfacing with the Blynk IoT platform, Arduino has a library for using Blynk. You can read the documentation here to learn more about using Blynk in general. For getting started, this was a handy instructable specifically for NodeMCU ESP8266 and Blynk.
Don't worry if some of these things don't make sense! The future steps will outline exactly what to upload, download, connect, etc. Do read through everything (yes, it's a long tutorial, but at least skim) before you start building!!! It'll help you figure out how things come together rather than just blindly following instructions.
Hardware
To begin, connect your hardware as shown in the pictures above. The neopixel should come to you with holes for soldering on wires. You will first need to solder wires to the holes labeled PWR (power), GND (ground), and IN (input for analog signals) before connecting the wires to the ESP8266's 3.3V, ground, and D2 pins (see this for pinout). As a rule of thumb, red wire is for power, black wires indicate ground, and I like to use blue for the neopixel's data line (connected to the D2 pin, which is capable of PWM signals).
Be sure to connect the capacitor in the correct direction: the capacitor has polarity, meaning that it does matter which side you connect in parallel to the neopixel's ground and power. If you look at your 1000uF capacitor, there is a grey strip down the side that indicates the negative side of the capacitor (you can see it in the fritzing diagram above too). This is the side that should be connected in parallel to the neopixel's ground. The resistor doesn't have polarity, so no need to worry about the direction.
In terms of creating a firm connection, the best way would be to use protoboard so you can solder the components together rather than just plugging the wires into a breadboard and risk them coming out. I used a breadboard because I was short on time, but again, protoboard is preferable. The nice thing about the breadboard is that it has a sticky back so I just unpeeled the sticker to stick everything to my lamp base. For the protoboard, you could screw it into the base using the 4 holes they usually have at the corners, or just tape/glue it down.
Arduino Code
The .ino Arduino code is attached at the bottom of this step for reference. It looks long and wordy but don't worry: much of it involves comments to explain everything. I also like to skip lines to add spaces for differentiating sections, which makes the code look longer.
Main parts to edit to fit your code:
- Blynk authorization token/code (emailed to you from Blynk when you create a device in the app: see next page for more info)
- You'll need a separate authorization code for each lamp!
- wifi domain name (between the two apostrophes ")
- wifi password (between the two apostrophes ")
Other than that, as long as you use my exact Blynk app and overall hardware (so use my exact Blynk app configuration in the next step, have 12 LEDs in your neopixel ring, use the ESP8266's D2 pin for neopixel data line, etc), you just need to upload that code exactly to your ESP8266. Note that you'll need to use different authorization codes for each of your lamps! See next page for adding separate devices and getting those codes. Don't forget to match the wifi domain and password to the lamp too, if they'll be in different locations. You'll probably want to edit other things depending on what animations and colors you'd like, or maybe even what pins you use. I've commented the code to help you with changing things as needed. (read through Adafruit Neopixel library's strandtest example code for ideas too).
Before you can use the code, you'll need to download the libraries that the code uses (the ones at the top of the code). Read through and follow this guide from Adafruit (start at "Using Arduino IDE") for what you need to do to set up for the ESP8266. Yes: you'll need to install the CP2104 Driver, add to the Additional Board Manager URLs in Arduino preferences, install the ESP8266 package (go to Sketch > Include Library > Manage Libaries... and search up what you need -- see picture below), and also install the other libraries at the top of the code for neopixel, Blynk, etc.
To upload code to the ESP8266 chip from the Arduino IDE, you'll need to select the correct board (NodeMCU ESP8266 ESP-12E), flash size, port, etc (see picture below). The correct port SLAB_USBtoUART won't show up unless you plug the ESP8266 to your computer. But once it's connected, and you're sure you've correctly connected your circuit in the previous step, you can go ahead and press the arrow in the upper left corner to upload your code to the board. Yes, it does take longer than your usual uploading-to-Arduino process. You'll see it compile the code slowly, then a string of orange periods .................. as it uploads (displayed in the Arduino window's bottom black part).
Now, here's a breakdown for the code. The first section includes libraries that the functions will use and initializes global variables (variables that can be accessed by any function in the code). The BLYNK_WRITE(virtualPin) parts control what is done when the widgets in the Blynk app (which are connected to virtual pins) are toggled (i.e. turned on/off, slider positions changed). There are 7 of these for the 7 virtual pins I use in my Blynk app. The next section of void colorWipe(), rainbow(), etc. are to define functions that the rest of the code uses. These functions are mostly borrowed from Adafruit's neopixel library example code (specifically strandtest). The last parts are your standard void setup() and void loop() that go in all Arduino code: void setup() defines operations that happen only once with the board is powered on, and void loop() defines operations that the board continually loops through when it's powered. void loop() mostly defines what animation the lamp will loop through based on the variable "animation" that I created.
Downloads
Blynk IoT
I chose Blynk over Adafruit IO for this version 2.0 lamp. Adafruit IO is great, but there were two things that Blynk had as opposed to Adafruit IO: an app interface and the ability to accept "blank" as a wifi password (so if you're connecting to a public wifi that doesn't have a password, you can leave the password section empty, i.e. just ""). My friend goes to hospitals often for treatment, so I wanted to have this capability in the occasions that she has overnight stays but wants some virtual company: she'd still be able to connect to wifi at the hospital.
Start off by going to the Google Play store or iPhone's App Store to download the Blynk app onto your phone. Create an account for free and make a new project. In the upper right corner, you'll see a QR code scanner button: use that to scan the QR code in the picture below to copy all my buttons and such into the new project. See this page for more on how this works ("share your project's configuration"). That page also provides useful information for sharing the project with your lamp's recipient later.
Of course, you can customize the buttons as you'd like! Swipe right to reveal what widgets you can add. You should understand what options you have for the widgets though: I've attached pictures (with notes in each picture) of the buttons' settings and suggestions for using them at the top of this step.
By the way, adding widgets costs points in the app, and everyone starts off with a certain amount for free. Adding additional points costs money ($2 for 1000 additional points). I ended up adding 1000 points to make my configuration work, but you can simply remove a button or two to make it work with the free amount.
In the project, you need to press the nut button in the top left (next to the "play" triangular button) to access project settings.
You need to add devices to the project to get authorization tokens/codes for each lamp, which you change in the Arduino code as previously mentioned. Press the Devices right arrow to create new devices. When you create a device, you'll see its token like in the picture below (blurred in red).
Once you have the code, remember to input the correct token, wifi domain, and password in the Arduino code for each lamp. You should probably input your own wifi credentials first to make sure each lamp works properly and debug as needed, but then update with your recipient's wifi domain and password before shipping it out.
Make sure you turn the app on in order to actually use your buttons! When the app is "on" (press the play button in the upper right corner, next to the nut button for settings), the background will become solid black instead of the dotted grid you see when you are in editing mode. If you've uploaded the Arduino code to your ESP8266 and plugged it in, the chip should automatically connect to wifi. Check this by pressing the small microcontroller icon in the top right corner (visible only when app is on): you should see a list of devices you created for the project and which ones are online.
Lamp Cover
For the actual lamp, I went with laser cut wood (1/8" birch plywood) and acrylic (transparent, 1/4", for the bottom face so the light shines through). The wood had cutouts that were unique to my friend and me, but I attached Adobe Illustrator files for the puzzle piece face designs (makes a 4" cube) for you to cut out if you like the shape (files are attached to this step, below). Warning: the bottom face has to be 1/4" thick for the pieces to fit together, in those files. If you want to make a different size or have everything with one thickness, use makercase.com to generate files for laser cutting a box.
Don't forget to leave a hole for the power cable to come out of the lamp. I forgot to include it but was able to use wire cutters to cut a small triangular hole through the 1/8" wood.
Sharing Lamps With Recipients
When you send the lamp to your recipient, they'll also need to download the Blynk app onto their phone from Google Play Store or Apple's App Store to control the lamp. You can either have them make a separate account or use your same login. If they make a separate account, you can share a special QR code for others to use for 1000 points (NOT the one I shared in the previous Blynk step; this QR code provides permission to use the same app as you, but they can't change any of the button settings or configuration -- read through this page, specifically "share access to your hardware"). You need to make sure you turn on the app (press the play button in the upper right corner so you see the microcontroller button instead of the nut settings button) in order for others to use the app.
I got around the 1000 points cost by giving my friend my login information so she could log into the app via my account. If you are sending these lamps to people who aren't that great with electronics (elderly folks, in general), I'd recommend spending the $2 dollars to create a shared link so they don't have access to your account and can't mess up your app settings. With this QR option (1000 point cost), they still have a clone of your app but can't change anything.
Using the App
Now, how can you use the app to control the lamps?
Turn the lamp on and off with the big power button (red when off, green when on). If the lamp is turned off, it automatically turns off all other buttons in the app and sets RGB to 0, 0, 0. When you press to turn the lamp back on, the lamp starts with pulsing white.
There are the three RGB sliders in the top right to control the RGB color output in the lamps' flashing. They update the color real-time as you are adjusting the sliders. You can also adjust the color with the zebra shaped color map at the bottom of the app. This is connected to the RGB sliders, so the sliders update based on what color you choose in the map, and vice versa.This map is helpful if you have a shade you want in particular but don't know the appropriate RGB number values.
There are buttons on the left side of the app with preset animations for happy, angry, sad, and meh. "Happy" causes the lamp to flash through the rainbow colors, "angry" makes the lamp flash between red and yellow, "sad" makes the lamp flash through blue and sky blue, and "meh" causes the lamp to create a rotating rainbow wheel. I chose the rainbow ones for happy and meh since they're more likely to be the default, everyday animations. Whenever you press one of the preset buttons, all other buttons will be turned off (i.e. if you were on "happy" but press "angry", the happy button would automatically turn itself off after a few seconds). Do note that it will take longer switching from the happy and meh animations because the lamp has to go through the full rainbow animation before it can change animation. If you turn off any of the preset buttons, the lamp will default back to blinking whichever color the RGB sliders correspond to. If you have any of the preset animations turned on but change the RGB sliders, nothing will happen: the preset animation dominates.
Before unplugging the lamp, press the power off button in the app as a good rule of thumb. Then press power on in the app when you plug the lamp back in. Do NOT adjust the app buttons when any of the lamps aren't powered on or connected to wifi (not the end of the world, but it will mess up the lamp operation). See next step for why...
**WARNING FOR PROPER OPERATION**
There is one loophole in the operation of the lamps. The Blynk interface doesn't allow me to selectively control what can be toggled when something else is on or off, but I put conditions in the code such that if you toggle something that shouldn't be toggled when the lamp is off or another animation is on, the toggle will undo itself: that took a lot of debugging but it works pretty well (demonstrated in the video above: the app rejects changes that occur when the lamp is off, and if the preset animations are on then any changes to the sliders don't affect the animation until the preset button is turned off)!
The one remaining pitfall is that if you toggle things in the app when the chip isn't connected to the internet, this automatic "undoing" function won't work and the lamp won't follow what the app commands. Then when you turn on the lamp, it won't reflect what you're doing accurately (no matter what, the lamp starts off with white blinking when you power on). To fix this, just press the big power on/off button: a power cycle will reset everything in the app so the lamp will function as expected.
Long story short: whenever you start up the lamp, just do a power cycle of the power button in the app to reset everything. Just do this if you ever unplug the lamp or use the app when the lamp isn't plugged in (or if the lamp suddenly isn't responding properly even when you give it time to react, maybe if your wifi randomly disconnects).
Finished
And that's a wrap! It's a nice gift for anyone you share a long-distance relationship with: make one for your parents before you leave for college or move to another state for your new job, make one for your grandparents when you have less time to visit them, make one to keep your SO company at work, etc.
Here are some additional variations you could do:
- You could flash through multiple colors (red orange yellow) instead of the faded pulsing I have
- Have color control for those multiple flashes (first red, second orange, third yellow) instead of just blinking bright and dim versions of same shade
- For that you would add a separate color map or set of sliders for controlling the colors that each animation cycles through (so instead of always red orange yellow, have it individually controllable so you can have teal pink white, green purple blue, etc)
- There are other animation types you can try out in the Adafruit Neopixel strandtest example code, like the theaterChase option.
- If you want to add a speaker breakout board, you could also have a music option for your lamps. Maybe have them play different music for different occasions. Or instead of music, voice recorded messages.
Have fun customizing the lamps! Feel free to message me with questions or comments.