Introduction: Network-Connected Lamps (IoT for Beginners)

A project for someone who lights up my life...

As a Christmas present (albeit an extremely late one now) for a long-distance friend, I wanted to build lamps that could "talk" to one another, as in "reflect each other's color animations when simulated." This involved a lot of frustrated screaming into pillows, late night confusion on why the circuit suddenly stopped working, and hours of debugging over hot cups of tea (not to mention weeks and weeks of research and taking notes to include for this long tutorial). But at long last, I have lamps that communicate through Adafruit IO:

  • In lamp #1, a softpot connected to neopixels controls the pixels' animations
  • When the softpot is pressed in a specific location, the pixels perform the corresponding animation
  • The arduino connected to the softpot sends this sensor reading to a raspberry pi
  • The raspberry pi is connected to the internet though a wifi dongle, so it can send the sensor reading to a feed in Adafruit IO
  • The raspberry pi of lamp #2 registers the new value in the feed and sends it to its arduino
  • This arduino animates its neopixels based on the value and all is good :)

Now, before anyone becomes nervous from the electronics and microcontrollers, allow me to assure you that I began as an absolute amateur. The farthest I had ever gone with Arduinos were the level 2 built-in sketches, I had never touched a raspberry pi before, and MATLAB was the only programming language I knew, besides how to print "Hello World" in python. Luckily, I had a EE friend to point me toward the right resources and help with troubleshooting (bless his soul). So if you're daunted by a steep learning curve, fear not.

Also, if you're worried about cost barriers, I did my best to minimize out of pocket costs of the components (~$80 for me). Admittedly, there are a few parts that would be best to borrow if possible, like keyboards and monitors, but try asking around or going to a local makerspace.

Video

Step 1: Table of Contents

TLDR: Go to step 6 to begin building a lamp, or just keep reading along to get background info as well.

I have a LOT of excess information in this tutorial besides the bare bones of how to make the lamps. This is partially my personal documentation of the learning process for future reference (I included my rough pseudocode, general thought process, research notes + reference links for different functions, etc.), but also a guide of things I tried out to help you if you want to make alterations to the design. For example, if you want to get rid of the Arduino component and control the softpot and neopixels through the raspberry pi, see the next step for how I got it to partially work without using logic level shifting. Oh also -- if you have any input on how to solve any approaches/problems that I encountered and abandoned along the way, please leave a comment!

The first few steps are general background info and things I tried: Choosing raspberry pi and arduino, intro to neopixels + softpot, adafruit IO, serial connection between arduino and raspberry pi.

After that is the entire workflow of how to build the lamps: files for the codes, setting up the micro controllers, building the neopixel + softpot circuit, etc.

The last step covers my final reflections and possible ideas to build on this lamp design.

Quick disclaimer: I rushed this project towards the end so there are still some buggy parts in the code/logic! The lamp functions but you need to send values to the feed twice: the timing is such that a value gets wiped before it can be sent, and I'm still trying to circumvent that. But the recipient is having heart surgery soon so I needed to get the lamp sent first and optimized later!

Step 2: Arduino Plus Raspberry Pi

Why do I have two micro controllers for this project? Well, the network connection to Adafruit feeds and dashboards requires internet access, and for arduinos that usually involves expensive wifi shields. Instead, I used a raspberry pi zero with a wifi dongle (~$15 compared to $30).

But why do you need an arduino then -- why not just control the neopixels and softpot off a raspberry pi? I originally pursued this idea, but had little luck getting reliable data from the softpot. Two main problems:

  • Neopixels use 5V logic while the raspberry pi zero outputs 3.3V standard
  • Raspberry pi zero is not capable of analog-to-digital conversion (ADC) by itself (so can't work directly with softpot)

I did my best to circumvent these issues (fueled by my desire to save money, as always). Even though adafruit doesn't recommend powering neopixels off the 5V GPIO pin of the raspberry pi, I managed to get away with it by connecting the 5V pin (GPIO pin 2) to the neopixel power, ground pin (GPIO pin 6) to the neopixel ground, and pwm pin (try GPIO pin 12 or 18) to neopixel data in. Then use Jeremy Garff's rpi_ws281x library to control the animations using python. See this guide or this one for how to install and use that library. If you're still worried about the logic level, you can use logic level shifters as described by Adafruit.

Now that the neopixels worked on the pi zero, I wanted to control them based on sensor readings of a softpot. There was surprisingly little documentation of how to use a softpot with raspberry pi, so I cobbled together information from tutorials with force sensitive resistors (FSR). Again, there's the problem with analog-to-digital conversion, as described here. You could get ADC chips to make the readings compatible with the raspberry pi, but frugal as always I looked into ways to use an RC circuit. The idea is that you have your FSR (soft pot in my case) and capacitor in series. Set the voltage to a square wave via pwm to charge up the capacitor. How fast it fills up depends on the value of the resistor. This documentation was helpful for setting something up, but no matter what I tried I got rubbish values. I thought it might be something with calibration, and it probably could've been done with an oscilloscope to reliably monitor everything, but I threw in the towel and got an arduino to handle both the softpot and neopixels -- no 5V conversion or ADC to worry about, not to mention plenty of documentation online.

Useful references:

Step 3: Getting Familiar With Neopixels and Softpots

All right, so what are neopixels? They're addressable LEDs that can be controlled by the micro controller of your choice. Here's Adafruit's Uber guide to handling them, if you'd like in-depth info. They expect 5V logic so raspberry pi are generally not preferred for controlling them (see previous step for my angst-y explanation). There are three main pins on the neopixels: power (connect to 5V), ground (connect to ground; it's the pin with the triangle), and data in (connect to a free pin to relay messages between the pixels and microcontroller for animation). An alternative would be DotStar LEDs, but neopixels were better documented for an amateur like me to begin using.

Now soft potentiometers, aka softpots, are resistive sensor strips that change their resistance based on where you touch them. They also have three pins: power (connect to 5V), ground (connect to ground), and wiper (outputs an analog signal -- connect to any analog input pin). Sparkfun has great documentation on how to hook them up in circuits and handle them, but the main thing to note is that there should be a resistor between the wiper middle pin and ground to hold the value at 0 whenever the soft pot isn't touched (i.e. so it doesn't "float," as the cool kids say). The leads are pretty fragile since repeated bending creates fatigue that causes them to snap easily, so I used plenty of heat strink for stabilization (and prevent the leads from touching each other, creating a short circuit.

For my lamp, I hooked up softpots to control the neopixels so that you would end up with different animations in the neopixels based on where you touched the softpot (i.e. based on the changing resistance of the softpot, which the arduino would read, analyze, and send instructions to the neopixel).

Summary references (for coding with arduino):

Step 4: Adafruit IO

There are many different platforms for IoT (ThinkSpeak, Blink, AWS) but the one I used is Adafruit IO.

Adafruit offers a platform for people to tinker around with Internet of Things (IoT) projects on io.adafruit.com. It's still in beta mode and admittedly a bit buggy, but it works well enough for my simple purposes. Essentially you have dashboards with blocks that can be stimulated (toggle buttons, sliders, gauges, etc.) and the data would be sent to feeds where you can monitor the blocks' actions. Data policies are here: the max rate is 2 samples per second, each feed can have 50,000 data points, and data retained for 30 days. This project is pretty simple (and timing not too crucial) so I didn't worry too much about encountering problems with data storage/collection.

Adafruit's tutorials (digital input and digital output) use npm for the package manager and node.js stream application program interface (API) and to familiarize myself with it I did my best to follow the tutorials for raspberry pi connection. However, I had a lot of trouble downloading the library dependencies using npm, so my friend suggested that I use python's pip instead. This is a great resource for using pip with adafruit IO, and this resource is an exhaustive list of using pySerial (for communicating between the raspberry pi and arduino via the serial port.)

This platform gives you an AIO key to put in the client field when you want to send and retrieve data, so while you don't need to know python pip, you will need to alter my python code to match your specific cases. Just a heads up!

References:

Step 5: Serial Communication Between Arduino and Raspberry Pi

Communication between the raspberry pi and arduino is possible via the serial port; for more in depth exploration of the serial monitor, see this. Essentially, when the arduino registers a value from its softpot, that value is sent to the Adafruit IO feed through serial port to its raspberry pi (which is the one that has internet access and thus access to the feed). The other lamp's raspberry pi notices a new incoming value and sends that to its own arduino via serial port to control its neopixels, thus synchronizing both lamp's animations.

Sounds simple in concept, but implantation is always a HUGE struggle; behind the concept were weeks of annoying debugging. Key problems:

  • I wanted to avoid using a USB connection so I wouldn't need to leave a USB hub to provide more ports to the raspberry pi (since it has two USB ports, one that would be needed for power and the other one for wifi). Thus I wanted to do serial connection through the TX and RX pins (transmission and receiving pins, respectively).
    • You would think that it's as simple as connected the TX of one to the RX of the other, and vice versa, but of course that doesn't work out. This is tricky because the arduino outputs 5V logic while the raspberry operates on 3.3V logic: thus, while the arduino's RX pin can just be connected to the raspberry pi's TX pin (since arduino 5V can read lower logic), the arduino's TX pin must go through logic level shifting from 5V down to 3.3V in order to be connected to the raspberry pi's RX pin. See this website for a simple guide, and this website for other suggested methods of doing so.
  • All right, logic level shifting. To save a little $ (and time for shipping), I build a simple voltage divider circuit using a few resistors (keep the resistors' power rating in mind so you don't melt the poor things!) before connecting the arduino TX pin to V_in of the divider and the raspberry pi RX pin to V_out.
    • Then make sure to follow the steps outlined here on preventing Linux (RPi's operating system) from using the serial port and interfering with your connection.
    • But of course that didn't work! D:
    • I played around a bit to try making it work. One thing is that to generate output on the arduino pro micro, you need to use the Serial1 class -- i.e. change the Serial.____ commands to Serial1._____ .
    • And... it still didn't work. I was stumped and frustrated so after two days of researching and testing, I just bought another $5 USB hub and used a USB A to micro B cable to connect the RPi to the arduino. And of course that worked the first time around.
  • Now that the serial ports are connected, everything's fine, right?
    • LEFT. (heh; word play...)
    • The tricky part this time is sending numbers through serial connection, since there are many classes. You could send what you think is a number, but once the other microcontroller reads it you might realize that it was sent as a string in ASCII code. But then your arduino code reacts to the ASCII code inputs separately and thus Houston, we have a problem...
    • It took a bit of trial and error to get the correct output to the serial port, but referencing this site I found Serial.parseInt() that did the trick for the arduino reading the raspberry pi's output as an integer.
    • And then it just came down to writing some code to make everything work...
  • Well, writing code is hard. Logic is difficult to get right. And data types smh.
    • I had a lot of trouble with getting the order of commands down D: so note for future me: be sure to write lots of pseudocode so you can plan your order/logic in advance!
    • A major problem I had was with Arduino's auto reset: I didn't know that starting the serial monitor for the Arduino also restarts the sketch. Documented here, here, here, and here: The first two links are forum topics of people having trouble, and the last two links are good resources explaining the phenomenon and suggesting alternatives.
      • I wanted my code have feedback: if it's in the middle of an animation, it should still check the serial port for communication from the raspberry pi to see if it should break out. However, by checking the serial port, it automatically broke out of the for loop since the sketch would restart. You can't imagine how much time I wasted trying to figure out what was going on (I had some inequalities that would break out of the for loop even though they shouldn't have -- 20 > 101??).
      • Two options:
        • Edit my python code so the raspberry pi would not send over values until you needed to break out, and then you'd just have to send the animation trigger value twice
        • Edit my Arduino code and use the Serial.peek() function (read the API, my friends)
          • peek() won't cause an auto reset but it'll return a byte of the serial message. Then figure out a way to correspond that byte to break out or now.

Good references:

  • raspberry pi communicate to arduino: pySerial
  • arduino communicate to raspberry pi: Serial

Step 6: Workflow Overview

A more fleshed-out explanation the workflow for building the lamps:

  • Prepare equipment
    • Make sure you have everything -- cables for hooking up to monitors, etc. as described in the materials step
  • Set up micro controllers
    • Arduino (no need to hook up to monitor -- just plug it into your computer)
      • Download the Arduino software on your computer
      • Dowload the .ino file for it (attached to this step)
      • Hook up the circuit with neopixels and soft pots, test on breadboard before soldering to stripboard
    • Raspberry pi (hook up to monitor, keyboard, mouse)
      • Ready your micro SD cards for use with a raspberry pi (flashing, installing OS)
      • Update existing systems (sudo apt-get update)
      • Set up Wifi for you and recipient
      • Set up Adafruit IO
        • Make an adafruit account and sign up to be a beta user
        • Create a feed that will receive and record data
        • Create a dashboard where you can adjust a slider to reflect softpot readings
      • Downloading python IDLE and .py code
      • Set up python code to run on set up (so no need for keyboard/monitor/peripherals on the pi zero)
  • Build other lamp
  • Build lamp covers

Step 7: Materials

Necessary components: (with approximate cost and applicable links) -- you might have some of these on hand, such as the SD cards (flash them yourself to save $$)

  • 2x arduino pro micro ($4 each)
  • 2x raspberry pi zero ($9 each with all adapters)
    • 2x mini-HDMI converter
    • 2x micro-B OTG USB
    • 2x 40 pins for GPIO
  • 2x micro SD cards ($4 each; at least 4GB or higher)
  • 2x neopixel rings ($7 each; I used 12 pixel rings to keep current requirements down, so I could power everything off one power supply)
  • 2x soft potentiometers/softpot ($5.50 each)
  • 2x 5V/2A power supplies ($6 each)
  • 2x wifi dongles ($10 each)
  • resistors (1kOhm or above should be fine)
  • heat shrink (to protect the softpot leads -- they're fairly fragile after repeated bending)
  • breadboard for protyping, stripboard for soldering permanence
  • electrical wire (solid core copper insulated in plastic sheathing like this)

Necessary equipment for operation: (besides the obvious ones like computer and internet access) (try to borrow from friends or go to a makerspace if possible)

  • computer monitor (with HDMI port)
  • keyboard
  • HDMI cable
  • mouse (NO gaming mouse or anything special, unless you have a powered USB port to the raspberry pi! Make sure it's compatible with your USB hub and with Linux -- for example, my wireless Logitech mouse didn't work since it requires Mac OS or Windows but not Linux)
  • USB hub ($6)
  • USB A to micro B cable (you probably have one from an android phone charger)
  • multimeter
  • soldering iron + solder
  • heat gun (optional but recommended for desoldering the TX and RX pins)

Materials for lamp: (feel free to come up with any other design of course, but I just went with a customized cube)

  • quarter inch plywood
  • laser cutter access or amazing scroll saw skills
  • wood stain
  • eighth inch acrylic
  • glue
  • vector graphics program

At least for me, out-of-pocket cost came to about $80 to make two lamps, but admittedly I had the computer monitor, soldering irons, and other equipment such as laser cutter and scrap wood. If you plan this as a Christmas gift, know that pimoroni.com offers significant discounts for many electronic components during Black Friday so if you buy your components then, you could still finish by Christmas... *wink nudge*

Step 8: Starting Up Arduino and Checking Range of Softpot

First we want to check the range of values of the softpot so you can assign animations to pressing different locations. Connect a softpot to an Arduino and breadboard as shown in the pictures above (power pin of the softpot to the + rail, ground pin of the softpot to the - rail, wiper pin to any analog pin of the arduino (A0 for me) with a resistor connecting that pin to ground).

Download the Arduino IDE on your computer if you don't already have it.

Launch it and download the zip file attached to this step. Then in the Tools tab at the top, select the appropriate board for your Arduino (Arduino/Genuino Micro for me). Plug an Arduino to your computer (cable depends on your model: for example an Uno needs a A to B printer cable while Pro Micro needed an A to micro B) and make sure it's recognized (select the correct port for it in the drop down menu, as in the picture above).

Unzip the downloaded file and open up the TestSoftpotRange.ino file. Press the verify button (checkmark in top left of window) to compile the sketch before the upload button (arrow to the right of the verify button) to send it to the Arduino. (side note: Yes, it's perfectly normal to have flashing red LEDs on your Arduino at this point. These are the RX and TX LEDs, which flash when data is communicated in a USB-serial connection.)

Take the time to make adjustments as you need -- if you used different pins, etc. Press the verify button (checkmark in top left of window) to compile the sketch before the upload button (arrow to the right of the verify button) to send it to the Arduino.

Now open the serial monitor (press the magnifying glass button in the upper right of the window). The softpot readings will be output in this window so press the softpot in different locations and record the range at the bottom, middle, top, etc. (may be slightly nonlinear so don't just record top and bottom). I only had three different animations so I just jotted down ranges for the bottom, middle, and top.

Step 9: Soldering Connections for Arduino

Now for the real Arduino code -- but first we need to prep the Arduino circuit. I say solder in the next steps, but you should probably check the circuit with a breadboard first before soldering onto stripboard since it'll be much harder to unsolder later.

Quick note before you start: do all of this with the arduino powered off (not plugged into anything from the USB)! And general rule just in case: connect ground of any component first.

See the images above (I'm so proud of my custom softpot svg for fritzing...) for the connections, but essentially:

  • Solder the Arduino pro micro's pins (or whatever you have) to the stripboard
  • Neopixel
    • Solder wire to the labeled power, ground, and data in holes
      • Solder the ground wire to the - rail of the stripboard
      • Solder the power wire to the + rail of the stripboard
      • Solder data in wire adjacent to pin 10 (just has to be capable of PWM -- pro micro pinout -- so just change the arduino's .ino file sketch if you use something other than pin 10)
        • Solder a resistor (1KOhm for me; ~470 Ohm recommended by adafruit) before the data input pin of the arduino to the data in wire of the neopixel to prevent negative effects of sudden spikes to the data in line
  • Softpot
    • Solder wire onto the three leads of the softpot
      • Solder the ground pin (left most, should have the white triangle) to the - rail of the stripboard
      • Solder the power pin (right most, opposite of ground pin) to the + rail of the stripboard
      • Solder the middle wiper pin to A0 (or any other analog pin to be read by the pro micro)
        • Add a resistor connecting the middle wiper to ground; this will prevent the value from "floating," i.e. it will stay at 0 when nothing is changing from the sensor's prospective
  • Extra connections to the Arduino
    • Use a piece of wire (insulated sheath, just strip the ends) to connect VCC pin of the Arduino to the + rail and solder it down
    • Use a piece of wire to connect the ground pin to the - rail and solder

Notes:

  • Heat shrink is not necessary but REALLY helpful to ensure that your soft pot's leads to break off (they tend to be fragile) or touch each other. At least use duck tape for stability, if anything?
  • I cut my electrical wire pretty long (5 inches or so) for connecting the neopixel and softpot because I wanted the neopixel to be up near the middle of the lamp, and the softpot to branch outside the lamp to be accessible. I also braided the wire for added structurally stability, but up to you.

Step 10: Uploading Sketch to Arduino

From the unzipped folder you downloaded two steps ago, open the other .ino file (NetworkedLamp.ino). This file requires the neopixel library too, so download the required library from here.

Quick disclaimer:I'm not great at coding, especially during the times that this code was revised in the early hours of the morning. That being said, please feel free to comment with suggestions on how to improve the logic/length/anything of the code -- I'd really love to learn.

Look at my .ino code and take the time to make any adjustments as needed: maybe you used a different analog pin so change line three, maybe you used a different data pin for the neopixel, so change line two. You may also need to change the softpot ranges in the animations to reflect whatever animations you'd like for whatever location in the softpot. That's where the values you recorded from the previous step come in. Here's a rough pseudo code overview of what this code does:

  • void setup () is a loop initializes environment, like baud rate, brightness, pixels to off, assigns which pins as data pin for neopixel or analog pin for softpot
  • void loop () governs the actual functions to be run
    • first the softpot is read
      • if not the rainbow animation range (under 25) (i.e. softpot was touched)
        • send that reading to the serial port so the RPi can add it to the adafruit feed
      • if reads something from the serial port (i.e. RPi sent it a value from the adafruit feed, so other lamp was touched)
        • store this number and do the corresponding animation instead
    • NOW for the animation to be done in this cycle
      • I assigned a flashing green cyclic animation for the bottom portion of the softpot
        • From the softpot testing in the previous step, I found this portion to correspond to values from 25 to 40; might be different for you, so check!
        • colorWipe function is defined later outside void loop()
      • Then the middle section (41 to 100) got a flashing blue animation and the top (above 100) got a flashing purple animation
      • if nothing is pressed, the default is a rainbow cycle animation (defined later outside void loop () )
    • BREAKING out of animations
      • if another place is touched, break out of the flashing for loop for animations
      • if something is available in the serial port AND it corresponds to a different animation than what's cycling through, break

NOTE: if you want the animation to go faster, increase the integer "fast." And to make the animations last longer (flash more times before auto turn off), increase the integer "times."

This sounds simple, but it took me a really long while to figure out the right order and location of aspects (breaking out of animations was a real pain) and the correct syntax for reading values from the serial port.

Step 11: Connections of Raspberry Pi to Peripherals and Arduino

Lots of wires to plug in:

  • Plug the HDMI mini adapter to the pi zero and use the HDMI cable connect the raspberry pi to your monitor (depends on your monitor, but you might have VGA connection, etc.)
  • Use the USB OTG cable to connect the pi zero to a USB hub.
    • For the USB hub, attach a wifi dongle, the keyboard, mouse, and a USB 2.0 cable (A to micro B -- might be a different cable but it should be able to connect to your Arduino, like an USB A to B printer cable)
      • Connect the Arduino with the USB cable
  • Don't plug in power yet -- we need an SD card!

Step 12: Flashing SD Card

NOTE: this flashing is to be done on your own laptop, not the raspberry pi!

The raspberry pi uses an SD card for internal storage, and the card needs to be set up with an operating system (OS). Some suppliers offer an SD card preloaded with NOOBS (standard package for the pi), but in case you just want to use 4GB or higher micro SD cards that you already have, you can wipe the SD card and install an OS by yourself.

Download Raspbian (or an OS of your choice) here and unzip the folder to reveal the .img file. I chose Raspbian Jessie with Pixel.

This will be different depending on Windows vs. Mac, but on my Mac I opened up Disk Utility to erase and reformat. It's as simple as selecting the SD card in the left hand menu, clicking the Erase tab, and ensuring that the selected format is MS-DAS (FAT). (pictures above)

Next is adding the OS:

  1. Open up a new window in Terminal and insert the SD card into your computer.
  2. Type in diskutil list and find your SD card in the list (my identity was /dev/disk2).
  3. Type diskutil unmountdisk /dev/disk2 (or whatever your identity was) to unmount the SD card.
  4. Then go to the folder with the OS that you downloaded using cd (so cd Downloads for me).
  5. Type ls to list everything in the folder and ensure that your .img file for the OS is there.
  6. Then type dd if=2013-07-26-wheezy-raspbian.img of=/dev/disk2 bs=2m (replace 2013-07-26etc with the name of your .img file and /dev/disk2 with the identity of your SD card). This will take a few minutes (~10min for me) so just be patient!
  7. Once it's done you'll see some line saying how many bytes were transferred in how many seconds. Your SD card is done. My log from Terminal is attached below.

References:

  • This for flashing SD card
  • This for specifically wiping the SD card on a Mac
  • See this nice guide for basic Terminal/shell commands

Step 13: Using the Raspberry Pi

Now that you have the SD card, insert it on the pi zero. Make sure the monitor is plugged in (plus all peripherals as described two steps ago) before powering on the raspberry pi by plugging the power adapter into an outlet. Now your system should boot up!

Note: you may need to configure your keyboard. My keyboard had UK settings as default so I went to settings > mouse and keyboard settings > keyboard layout > English (US).

Quick rules of thumbs:

  • As much as possible, don't hot wire components (i.e. Turn everything off before adding peripherals. The sudden current draw may cause your system to crash, and losing your hard work is not fun D:)
    • It was OK for me to plug and unplug my arduino for troubleshooting and testing iterations of the code, but altering any circuits to connected powered pins (GPIO on raspberry pi, breadboard for arduino) made everything crash from time to time
  • If you need to urgently add anything to a circuit, at least plug in ground first! (but avoid doing this!!)
  • Do not simply unplug the power to turn off your raspberry pi: shutdown your system using the shutdown button in the start drop-down menu or type sudo shutdown -h in Terminal (the command line)
  • If nothing's working, check your current draw and connections/outlets: it's the little things that you don't see that will lead to lots of frustration
    • Your power supply might not offer enough current to power all your peripherals (keyboard, mouse, monitor, neopixels, etc.) so double check with conservative estimates!
      • My rough math:
        • Each neopixel uses max of 60 mA, so for 12 that's a max of 720 mA
        • Wifi dongle: max of ~500mA
        • Mouse, display, and keyboard: max around ~200mA
        • I have a 2A power supply so 2A - 720 mA - 500 mA - 200 mA = 580mA left; plenty for anything I didn't account for
    • Sometimes the bug isn't in the code; don't be like me and tear your hair out over your Arduino code just to realize that you never connected VCC to the + power rail...

Step 14: Setting Up Wifi (via GUI or Command Line)

To set up wifi, you should probably be able to just click the wifi symbol in the upper right corner of the screen, find your domain, and enter the password. Alternatively, you can set up wifi via the command line. You'll need to do that in order to add the recipient's wifi information in advance. Since I still wanted to keep most of the project a secret from the recipient, I "discreetly" asked her for the domain name and password for her home network and followed that command line tutorial to add it to the system for auto recognition. Even so, I made sure the raspberry pi could be accessible in the lamp in case that didn't work out (or if anything needs to be fixed/updated in the future).

Another thing: this project was rushed over before the recipient had a heart surgery operation, so I wanted this lamp to be portable in the sense that it wouldn't be too dependent on wifi. Yes, the lamp will still change color animation even without wifi, but it's nice to have the network aspect present too... In any case, I planning on doing this by telling the friend to create a mobile hotspot (of course, with the pretense of being fascinated in seeing how that works on an iPhone -- I should become an actress if my engineering major doesn't work out...) and adding that domain/password combination to the system again through command line. Haven't tried this yet but will update later when I do...

Step 15: Setting Up on Adafruit IO

Begin by creating an adafruit account and signing up to be a beta user.

Next, create a feed. Follow Adafruit's tutorial on feeds to create a feed (complete steps up to "Deleting a Feed"). Nothing really special here, though if you'd like email notifications every time the lamps are toggled, you can do so by turning on that notification setting on the right.

Now it's time to create an online dashboard, where there's a simple slider for you to remotely control the lamps if you'd like. Follow Adafruit's tutorial on dashboards to create it. For the section "Adding Blocks," add a number slider. Select the feed that you created previously before naming it whatever you'd like (person's name in my case), set min and max values (0 and 150, respectively, to match the relative range of outputs for the softpot), a step size (1 so I could have more values to slide between), and the slider label (left blank for me). I also created a line graph block to monitor the lamp's values over a two hour refresh interval so I can see when the lamp has been played with.

Additional resources:

Step 16: Python for the Raspberry Pi

The OS that I put on my SD card came prepackaged with Python IDLE (integrated development platform for coding with python) so I used that for writing my code. If you don't already have it, you'll need it (or something similar) to alter my code to fit your adafruit account! Download here.

Download the python file attached to this step (it's also called NetworkedLamp.py from the previous zipped folder) and open it to view the code (In IDLE, just go to file > open).

Quick disclaimer: I'm not great at coding, especially during the times that this code was revised in the early hours of the morning. That being said, please feel free to comment with suggestions on how to improve the logic/length/anything of the code -- I'd really love to learn.

Downloading packages for the python code:

  • You'll need to install python pip if you don't already have it: type in apt-get install python-pip in command line to do so
  • After, run sudo pip install adafruit-io install the library to interface with adafruit io

Editing the code:

  • Where you see aio = Client('INSERT YOUR AIO KEY'), insert your key for adafruit (click on the golden key icon at the top right) between the apostrophes.
  • You need to set up your connection to the arduino via USB (or if you managed to get it to work with the TX/RX pins, please let me know!) for the ser = serial.Serial('/dev/ttyACM0',9600) part --> specifically the /dev/ttyACM0 part to match what your raspberry pi recognizes as the arduino just in case (the 9600 is the baud rate, which must match the baud rate from the arduino)
    • To do figure this out:
      • Open a window in Terminal or Command Line
      • Type ls /dev/tty*
      • Plug in your arduino to the raspberry pi and type the same thing: the new name that appears is the name of your port that should replace ttyACM0
  • You'll also need to update every instance of the name of the feed (in my case, 'Monique') with the name of your lamp's feed.

Step 17: Run on Without Monitor Etc.

To let this lamp run without a monitor or keyboard, we need the python script to run on the raspberry pi automatically when it is powered on. To do this, we need to put this command in a file that tells the raspberry pi what items should be executed as soon as power is supplied.

I followed this great tutorial and this one too (different file but same idea), but essentially you access the login commands of the raspberry pi, set up the pi default user to auto log in, using the nano text editor to add the sudo command to run the python script inside the /etc/profile file to be run on start up, then reboot and test.

Quick note: the first method of doing this (first link above) means that the script will run whenever the default pi user logs in, further meaning that the script will run whenever you open a new terminal session (SSH, etc.) you'll auto run the script. Just something to think about...

Now reboot (sudo reboot) and check if that worked by pressing on your softpot (plug in your arduino to the raspberry pi if it isn't plugged in already): the adafruit feed should be updating with the sensor value even without the monitor on, etc.

Step 18: Other Lamp

Now that you have one raspberry pi + arduino set up, simply repeat the entire process with your other raspberry pi and arduino. All the code should be exactly the same, wiring is the same, etc. Just keep in mind that the wifi domain for your recipient must be added (via command line: see step 14) on at least one of the lamps so that it can be automatically recognized when you send the lamp!

To test: just plug in your raspberry pi's to power (without monitor/keyboard/mouse -- just need the arduino and wifi dongle plugged in) and press the soft pots to watch the synchronized animations!

Step 19: Lamp Cover

I customized the lamp cover for the recipient. This involved laser cutting and staining a simple wooden box with cutout designs on each face (with themes from FFX, Harry Potter, RWBY, and Studio Ghibli). To cover the cutouts, I put acrylic squares in the windows and paper behind the acrylic to diffuse the light. Some squirts of E6000 (bonding acrylic to anything is tricky...) later, I had a lamp cover!

I won't attach my .ai file so as to keep this lamp as "one of a kind", but you can see instructions on how to isolate vector paths for laser cutting in one of my other projects (goes over how to create a laser cut cubic lamp) using any common graphics software like Adobe Illustrator, Inkscape, Corel Draw, etc.

I made this lamp so that it wouldn't be fully shut: then the electronics inside could still be accessed for future debugging (I know I still have some improvements that could help this code work better..) or changing wifi domain if people move, so the bottom is detachable. Then the USB port for power to the raspberry pi just sticks out for easy access to the power adapter, and the softpot snakes out and sticks to the side for easy animation changing.

Be sure to glue/bolt/tape the electronics down to the bottom of the lamp! You can make the top part detachable to access the electronics, but it should still be firmly attached to a face of the lamp so that when you ship everything it won't jostle around too much and get destroyed in the hands of a skipping mailman... Notice that the raspberry pi has holes in the corners for M2.5 bolts (may be different for different boards) -- you can use these to drill holes into your wood to fasten the board down. My protoboard also had holes for bolts so I used those too. Alternatively lots of duck tape and glue should work.

Step 20: Reflections

To be quite transparent, I'm exceedingly pleased with how this project turned out, given my minimal experience with microcontrollers. The countless hours that I poured into online forums for debugging and figuring out next steps sometimes had me second guessing and tempted to lower my standards for success. I planned everything out excruciatingly slowly (even this tutorial had its own ~3 page planning document/outline...), but I gained so much knowledge from the iterative process: troubleshooting, coding, electronics (even how to create my custom parts in fritzing!), IoT, and patience (especially when I accidentally burned two arduinos within a day of each other by making the same mistake: sleep is quite useful, my friends).

It's a great project to learn more about the possibilities of interfacing micro controllers with the internet, but it's also just a great gift. My friend has gone through difficult times, and I felt motivated to make her something that could help her feel treasured despite any flaws she finds in herself. Not to mention the fact that she's having heart surgery soon: something to keep her company would be nice.

Further improvements for the future:

  • Like I said, there's still some parts in the code that need to be fixed: the lamp functions but you need to send values to the feed twice: the timing is such that a value gets wiped before it can be sent, and I'm still trying to circumvent that. Thankfully updating the arduino code is fairly simple: ask the person to plug in the arduino to a computer and upload the new sketch. The raspberry pi is trickier since it'll need keyboard/monitor (unless you work headless: I haven't tried it but it should work?).
  • Lights are interesting, but things like sound and motion would be pretty cool too.
  • Lamp covers can have interesting themes: try a companion cube from Portal or blocks from Minecraft? Or cut up a soccer ball for fanatics, etc.
  • I'm still hung over about my inability to connect the raspberry pi to the arduino via the TX and RX pins; it's not so much the additional $5 cost of the USB hub but the amount of time and researching I spent on that topic. It's still something I'd like to work on and figure out.
  • I'd also like to do a version in which only the raspberry pi is needed (get rid of the arduino). The lack of ADC could possibly be circumvented with the suggestions I found in step 2, so I'd just like to explore that possibility -- good learning experience.

As always, feel free to leave comments and questions below, and I'll reply when I can. Enjoy!

Comments

author
mocinoz (author)2017-03-27

great project, with a lot of detail and excellent references.

author
watchmeflyy (author)mocinoz2017-04-02

Thank you; I appreciate your kind comment!

About This Instructable

2,295views

45favorites

License:

Bio: In which I turn the thoughts from my head into objects in my hands
More by watchmeflyy:Controlling Lights With Your EyesLED Firefly EarringsLayered Sculpture Lamps
Add instructable to: