Introduction: RPi-Zero IoT Event Indicator / Color Lamp

No additional micro-controller, & No HAT add-on module required.
The RPi-Zero does it all. Better yet use a RPi-Zero W !

Sample use: Web Service state Indicator (e.g. DowJonesIndex tracking), Political or Sports event status indicator, mood light, track a sensor, you name it. View the video in step 6.

The Raspberry-Pi only has one hardware supported PWM line. This project needs 3 PWM lines, so I used a software driven PWM 'c' library (, which should already be installed.

I broke up the processing into 2 processes. One, interrupt driven, switching the control lines to the LED as needed, getting its marching orders from its 'stdin' stream. The other is an event driven nodeJS server utilizing socket IO. This is to prevent things like light flickering while ensuring responsiveness. The combination typically uses less than 5% of the CPU. During times of continuous color updates (via sliders &/or many clients) it can easily use over 50% (especially when also using the browser in the Pi-Zero GUI). Note that when a change comes in, update notifications go out to all the open socket clients.

Step 1: What You'll Need

Optionally, depending on how you want to connect the components

Step 2: Pi-Zero Setup, and Prep for Development

Follow this initial setup for your PiZero, to made it ready for development...

Once you have a microSD card with NOOBS setup then:

Plug the microSD card in.
Attached a low power USB Hub with a Wifi dongle, keyboard and mouse (You may use a wireless mouse and/or keyboard, either way it may, but not likely, require external power to the hub). I used adapters and a hub I already had.

Now attach a Monitor and a microUSB power adapter and It will boot up. Continue and finish the directions on setting up Raspbian, Debian Linux, as seen in the noobs-setup link above.

Additionally, I had too low of a resolution. So I added these lines to /boot/config.txt


The hdmi_mode=58 works for my monitor, your's may need something else.

refer: make-raspberry-pi-use-full-resolution-monitor and

After booting up the Pi-Zero goes into the GUI interface.

To make use of the full size of my microSD card I used the raspi-config #1 'Expand Filesystem' selection.
From the command line, in a terminal window, enter 'sudo raspi-config'
Refer to: documentation/configuration/

Also I changed these settings under #5 'Internationalization Options'

  • Locale: en_US.UTF-8 UTF-8
  • Timezone: America … Los_Angeles
  • Keyboard Layout: Generic 105-key (Intl) PC … English (US)

For me the Great Britain keyboard standard (that Raspbian comes pre-set for) was making much of my edits a real chore.

Change these settings as needed, appropriately for you. Note that you need to use the arrow keys and the tab key in order to navigate in 'raspi-config'; and after a selection it may be very slow to respond.

I found it no problem to connect to the internet with a WiFi-USB dongle (I used 2 different ones). I simply had to enter my WiFi access key-password using a pull-down in the upper right of the GUI. Once I did this it would automatically connect after any reboot/power-up.

Now I was ready for general development.

To get to this point you can take many paths. Up to this point, I have not given great detail here but there are many methods and configurations described in greater detail on the web. Including one for a headless setup where you would use a remote ssh terminal window on your personal computer to do the development steps to be given in this instructional.

Step 3: Development Environment and Tools

For the system configuration setup and software I developed for the project, I did the R&D on a Raspberry Pi-2; for it has a quad-core CPU making its browsing and code development, with multiple windows, a lot faster. You can, of course, use any model Raspberry-Pi to realize this project.

To setup Node.js (event-driven I/O server-side JavaScripting support) I did the following...

sudo apt-get update
sudo apt-get install nodejs npm 

Adding these nodeJS packages (npm is Nodejs Package Manager)

npm install express
npm install

References: Fast, minimalist web framework Socket.IO enables real-time bidirectional event-based communication

Step 4: The Hardware

The resister values used are all different, as the voltage drop and efficiency differ for all three LED colors segments. The GPIO High output levels were all approximately 3.2 volts. Each LED segment was tested to ensure it consumes less than 20ma maximum and about 40ma all together (<50ma max total allowed), which the PiZero can easily handle. I got as much output brightness as I could, directly driving the LED; which is plenty for my needs. To drive higher currents, for a much brighter output, intermediate drive transistors could be used with a common anode LED with its anode connected to the 5v line.
PS: As my various White levels are coming out a little blueish, 27 instead of 24 Ohm would have been a better choice for me.

Notice I used a header with male pins, and connected to the LED legs with F-F jumpers. This kept down the overall height. I soldered the resisters into the middle of the jumpers. Using no circuit board or solder-less board, along with the use of a right angle micro-USB to USB adapter for the WiFi dongle, made the final assembly fairly compact.

For a diffuser, I recommend a ping-pong ball (it is easy to drill a hole just big enough to insert your 5-8-10 mm LED in). Or cut off the top of an LED light bulb (one which uses a Plastic diffuser). For this mark a line, with a fine point sharpie, where you want to cut, and use a Dremel like tool with a thin cut-off attachment. If you like, a nice small cut glass jar or drinking glass may be used. Once you have settled on one diffuser, glue it down to the top of the case.

For demonstrations I like to use a small Li power-bank placed inside the case. This unit seems more impressive totally wireless. Of course, it will have a limited operating time in that configuration. For on going normal operation I simply use a micro-USB wall adapter.

Step 5: Project Software

I used two programs, a Node.js process talking to a child process via it's stdin data stream.
This is so they can each do what they do best and operate as independent processes at their own pace.

Here is what I did:
But you don't have to, as I have provided a tar-gzip file which contains the resulting file-tree.

NodeJS server-side setup:

	cd ~
	mkdir node_rgb
	cd node_rgb
	mkdir public 

put 'index.html' and 'style.css' into the '~/node_rgb/public' directory
put 'rgbDriver.c' and 'rgb_main.js' into the '~/node_rgb' directory

Compile/build the c process 'rgbDriver':

	cd ~/node_rgb
	cc -o rgbDriver rgbDriver.c -lwiringPi -lpthread

Downloading and expanding the equivalence

To download node_rgb.tgz (below) to your Pi-Zero into your home directory (~pi) you could do one of the 3 following :

  1. Download from the browser in your Pi-Zero's GUI
    Move the file to ~pi/
  2. In a terminal window connected to you Pi-Zero:
    cd ~pi

    mv FZBF9BDIL6VBHKF.tgz rgb_node.tgz

  3. Download from a browser on your desktop computer.
    Use WinSCP to copy it to the ~pi directory on the Pi-Zero

After performing #1 2 or 3 above ...

cd ~
tar -xzvf node_rgb.tgz
tree node_rgb
  ├── public
  │   ├── Dow_Jones_Index.html
  │   ├── index.html
  │   └── style.css
  ├── rgbDriver
  ├── rgbDriver.c
  ├── rgb_main.js
  ├── start_rgb
  ├── kill_rgb
  └── track_dji

The resulting executable (from above) 'rgbDriver' can be utilized independently of the Node.js interface process.

To verify that this driver and the hardware are working, feed sets of three values (of 0-255), separated by a space, to the driver. Like 'echo 255 0 0 | ./rgbDriver' for red or 'echo 0 255 0 | ./rgbDriver' for green. Note that the “./” tells the OS to find our program 'rgbDriver' in the current directory. When you issue a ^c (cntl-c) to stop the driver the led may or may not remain on. Alternately, you could interactively feed its values. Try typing, from the command line, these lines one after the other and watch the LED.

0 255 0
100 0 100
255 255 0

Be sure you don't have 2 of these processes running in parallel.

To launch the full software application suite, including the Node.js server use this command:

	sudo node rgb_main.js

Then use cntl-c when you want to stop the Node.js server.
Launch it with

	sudo node rgb_main.js&

to have it run in the back ground, but then you'll have to use a 'sudo kill -9 pid' command to stop it. If this command looks alien to you, then review the output of these commands: 'man kill' & 'man sudo'.

Use a browser, on your desktop, tablet or phone, which is connected to your local network. Go to
http://raspberrypi:8080/ or if that does not work use the ip address of the device (obtained from the cmd 'ifconfig') something like plus the port specification :8080 or if using the Pi-Zero's GUI: localhost:8080 will work.

Operate the RGB sliders, on the page that comes up, and watch the RGB-LED lamp follow along.

Other helpful commands
Note that if you end up with more than one 'rgbDriver' running at one time you are likely to get unpredictable behavior. If you try and run a second copy of rgb_main.js it will error out.

This command will list all of the related processes:

	ps aux |grep rgb 

This command will kill all of the nodeJS processes, along with 'rgbDriver' child processes:

	sudo ps aux | grep node.*rgb | awk '{print "sudo kill -9 " $2}' | sh

Stand alone operation

To have the Pi-Zero start up the Node.js server app when it boots up... using your favorite editor (e.g. nano ~/.bash_profile), type in the following lines & save to ~/.bash_profile

cd node_rgb
sudo node rgb_main.js &

To keep from getting nuisance error messages when opening a terminal window use conditional codding like the shell script in the 'start_rgb' file

When the Pi-Zero is running embedded, without a keyboard, mouse, or monitor; the Graphical User Interface will take minimal CPU time, as there will be no user interaction. I do not disable the auto GUI start-up, as the Pi-Zero has more resources than needed, in this case; and I like being able to connect a few cables and use it, at any time in the future. Though, this is not necessary as you can use a remote SSH terminal (e.g. PuTTY) to do any needed maintenance.

Using it as an Event monitor

I created a web page for monitoring the daily change in the Dow Jones Index. It's source can be used as a guideline for your own page which uses some web data and drives your Pi-Zero indicator accordingly. This page gets its (json) data from a Google web service. There are many forms of web services, so you will have to research the one that you want to use to determine the JavaScript code to access it.

If you would like to use your device, as do I, as a dedicated, stand-alone, Dow Index change Indicator add these lines to the end of the ~/.bash_profile file, or as desired SSH in and issue the second command line. If you subsequently want to utilize remote control 'kill -9 ' the resulting epiphany-browser process.

 sleep 20
 epiphany-browser --display=:0.0 localhost:8080/Dow_Jones_Index.html &

The indicator will illuminate a light gray given a value of 0. It becomes more and more green with higher values. It is brightest pure Green at about 250. Higher yet values cause at first a shallow flash, up to a deepest flash at about 500. For negative value (daily drops in the Dow) it does similar, but in Red.

UPDATE May 2018

I have created a new web page (SolarStorm_devCon.html, attached as a .txt file, due to .html file not uploading) which gathers GeoMagnetic storm info (which could foretell of a devastating CME, EMP) and uses that to present a color scale reflecting a sort of Geo-Storm 'DevCon' Index. indicating the potential of a disaster due to a Electromagnetic pulse (EMP) resulting from space weather, presumably solar flares or a Coronal mass ejection (CME). Use it like you would have used "Dow_Jones_Index.html".

Step 6: Remote Web Page Control

At this point you can control your IOT color Lamp from anywhere on your local network.
How to make it visible across the public internet is not part of this instructable.
If you do setup a public IP for your device, then you'll need to utilize that IP in the open socket command in the JavaScript of your pages (e.g. ~/node_rgb/public/index.html)

I am planning to use my Pi-Zero IOT device as a real-time color indicator for the day's change in the Dow Jones Index. I created a page that does that, which gets json data from
I further created a few web pages for demonstrating the wide range of uses for this small IOT device.
Rather than put my PiZero on the public Internet, I hosted the pages on my existing public facing web server (currently @ aka: when my free Dynamic Domain Name Server is operating), which is running on an original version B Raspberry-Pi.

In the code on my remote pages I opened socket connections to
I had fixed my Pi-Zero's ip to To do similarly follow the directions at setting-up-raspberry-pi-with-wifi-and-a-static-ip under the heading: Static IP Address.
So if you setup your PiZero to be at on your local network, these pages, opened up from my web site, will communicate with your device, as the connection is done from the client side.

Here are those pages which I used to test and operate my Pi-Zero IOT lighting device. If you bring up these pages ( aka or any of the pages framed on that page) the client-side JavaScript will drive your created IOT light (given it is running at this url “”) If you like you can copy the source of any of those pages and modify to your liking.

With the first page you can set your device to any color. The LED lamp and the color you see in the web page will track fairly well. The resister values used can be tweaked (as well as the monitor) to get them more truly matched. I spent little to no time ensuring that they matched. This page will update its color whenever anyone else changes the color and the server sends out the updated info message.

One page is a simple button controlled Traffic Light.

There is a page designed to track a sports contest (e.g. football, basketball, baseball), an election, or even adapted for a fund raiser or DEFCON alert level style indicator. The scores (or committed electoral votes) could be automatically obtained from a web service or scraped off some other web page. I don't have an automatic feed driving my Contest_demo page. Someone with the right know-how could add a power driver to run high power LED flood lights and bathe a room (or sports bar) with a team's color when they are ahead. Unfortunately I am too late with this instructable for this year's super-bowl parties, but in time for the 2016 election.

Then there is the page similar to the one I'll use to turn my device into a Dow Jones tracking indicator. The slider and buttons are only on the DJI demo page for demonstration purposes. In the source for this page there is code I developed to re-color a green-screen inspired image; with enough comments that you may also find it useful.

Only the first of these 4 pages (along with the Pi-Zero based index.html page) listens for server update messages, and refresh accordingly. All the rest only send to the server.

Raspberry Pi Contest 2016

Participated in the
Raspberry Pi Contest 2016