White Noise Night Light




Introduction: White Noise Night Light

About: I build things.

This is a project I made for my 1-year-old for Christmas. Honestly though, it was a sanity present for me and my wife. It's a white noise machine that can play multiple different sounds selected through a web interface, and also incorporates lights that change color based on the time (red lights mean be in bed, yellow mean you can play in your room, and green means it's ok to come out). Since my son is too young to tell time, a color-based night light seemed like a really good idea.

It's a really easy project, and since I've already written the code, it's maybe a 1 out of 5 on the difficulty scale. If you have toddlers that bother the heck out of you way too early in the morning, you'll want to make one.

Step 1: Parts List

1. Raspberry Pi Zero W

2. Some kind of case (I used this one from Amazon)

3. Blinkt from Pimoroni

4. Speaker Phat from Pimoroni (You could also use some other DAC with cheap speakers)

You will need to have some basic soldering skills to put together the speaker phat, there is a link with step-by-step instructions from the product page, so you can't screw it up.

5. [OPTIONAL] Panel mount micro USB cable - from Adafruit

6. some connecting wires or jumpers

That's it!

Step 2: Burn Raspbian and Hook Up the Boards

I am using Raspian Stretch lite for this build. So burn that to a microSD with whatever tool works for you, then fire up the pi. If you need help getting a headless pi to connect to your home's wifi and enable ssh, there are plenty of tutorials online that can show you how to do that, but you will need to make sure you've done that for the rest of this to work.

Using http://pinout.xyz you can pull up both boards and get their pinouts on this site. The Blinkt boards only requires 4 connections, and the Speaker Phat needs 9.

It should look like the photo when finished. Now we need to test that everything is working.

Step 3: Installing the Required Software

Now that we're connected up, we'll need to install the software required to run the Blinkt and Speaker Phat boards. SSH in to the pi, and you'll find yourself in the home directory. Enter the following:

curl https://get.pimoroni.com/blinkt | bash

and then once that's complete, this:

curl -sS https://get.pimoroni.com/speakerphat | bash

That will install everything needed for both the Pimoroni boards. If you enter the ls command, you should see a Pimoroni directory. So now let's write some code and test the Blinkt board.

Step 4: Writing Some Code and Testing It Out.

Make a directory called "scripts" by typing mkdir scripts and we'll keep everything we need to run in there. So cd scripts to get yourself in to that folder.

Now, what we want are red dim lights for night time, yellow dim lights for quiet play time, and slightly brighter green lights when it's ok to come out. For me, I wanted red lights from 7:30pm to 6:15am, and at 6:15am they would turn yellow for an hour, and then finally green at 7:15am. I also wanted them to turn off at 8:30am when no one was likely to be in the room.

There are two ways to do this. The first (the way I chose to do it) is with four different scripts, run from cron jobs. The other way to do it, is one script, that includes a time function that is run at startup. I actually wrote the script to do it that way first, but it seemed less efficient than doing it based on cron, so I switched it up. If you want the "one script" method, let me know and I can post it in the comments.

So, let's start with the red script. Type touch red.py, then nano red.py. Then enter the following code.

#!/usr/bin/env python
import blinkt
blinkt.set_pixel(3, 128, 0, 0)
blinkt.set_pixel(4, 128, 0, 0) #sets pixels 3 and 4 to red

Do the same for yellow.py and green.py.


#!/usr/bin/env python
import blinkt
blinkt.set_pixel(2, 128, 128, 0)
blinkt.set_pixel(3, 128, 128, 0)
blinkt.set_pixel(4, 128, 128, 0)
blinkt.set_pixel(5, 128, 128, 0) #sets pixels 2, 3, 4, and 5 to yellow


#!/usr/bin/env python
import blinkt
blinkt.set_all(0, 128, 0) #sets all pixels to green

And finally, we want a script to clear the Blinkt when it's not needed (lightsout.py):

#!/usr/bin/env python
import blinkt
blinkt.set_all(0, 0, 0) #sets all pixels to off

That's it. To test type python red.py and see if the two middle pixels light up red. Then type python lightsout.py to clear it. That's it! Next we'll have to set those in the cron tab so they run at when we want them to.

Step 5: Adding Those Scripts to Cron

In the SSH terminal type crontab -e

scroll to the end of the file and add the following lines:

15 6 * * * python /home/pi/scripts/yellow.py
15 7 * * * python /home/pi/scripts/green.py 30 8 * * * python /home/pi/scripts/lightsout.py 30 19 * * * python /home/pi/scripts/red.py

That sets up the scripts to run at the times described in the previous step, go ahead and adjust these to suit your needs.

That's it for the nightlight! Super easy. Now let's move on to setting up the White Noise portion of this build.

Step 6: Testing the Speaker Phat

The easiest way (in my opinion) to test out the Speaker Phat is by installing sox and running some static from the command line.

sudo apt-get install sox

Once that's installed, we can try some sample play commands. This one should sound like waves.

play -n synth brownnoise synth pinknoise mix synth 0 0 0 10 10 40 trapezium amod 0.1 30

How relaxing! Ctrl+c will stop it. But, what's that? There are a bunch of LEDs across the face of the Speaker Phat lighting up, and we can't have that interfering with our Blinkt lights. So lets turn those off.

To do this, we'll need to modify the /etc/asound.conf file and remove the VU meter plugin, so it wont even try to drive the LEDs in the first place. I did this by simply renaming it. Type this command mv /etc/asound.conf /etc/asound.conf.bak I found this through a bit of Googling, so there might be a better way.

Sox works, and that's great, but I planned on using some loopable MP3s for the white noise part of this machine, so I needed a different player, preferably something really light-weight. mpg123 is what I settled on. Install that now with sudo apt-get install mpg123

Ok, now that we know the Speaker Phat works as expected, time to build the interface and corresponding scripts.

Step 7: Setting Up a Small Webserver and Webapp

Flask is a micro web framework written in Python. It provides all the functionality we need for the webserver (which is going to act as an app). Install it with the following command:

pip3 install flask

That will take some time, so wait it out. Once it's complete, we're going to need to build up the folders we will need to pull from when the website runs, and these folders have specific names. Let's start with a place to host the website. From the home directory, make a new directory called www with mkdir www. Now cd www in to that directory. In here we need two more directories, one called static and another called templates.

We also need a place to put our loopable MP3s. I made a directory in the home directory called "sounds" for this. I found my MP3s by searching for loopable whitenoise MP3s on Google. Lots of free places to pull from. I used WinSCP to upload the files.

You might want to test them with the omxplayer command below playing with the --vol -### part to dial in the right volume level for your room. Again a Ctrl+C will stop the player.

Now that we have all those in place, lets write some python to stand up the webserver when the pi starts up. Go back to the www directory and start a new file called webapp.py (nano webapp.py) and insert the following code


from flask import Flask, render_template, request, redirect
import os

app = Flask(__name__)


def index():
    return render_template('index.html')

@app.route('/rain', methods = ['POST'])
def rain():
	os.system("mpg123 -f 8000 --loop -1 ~/scripts/sounds/rain.mp3")  <br>	return redirect('/')

@app.route('/waves', methods = ['POST'])	
def waves():
	os.system("mpg123 -f 20500 --loop -1 ~/scripts/sounds/waves.mp3")
	return redirect('/')

@app.route('/whitenoise', methods = ['POST'])	
def whitenoise():
	os.system("mpg123 --loop -1 ~/scripts/sounds/whitenoise.mp3")  
	return redirect('/')

@app.route('/stop', methods = ['POST'])	
def stop():
	os.system("killall mpg123")  
	return redirect('/')

if __name__ == '__main__':
    app.run(debug=True, host='')

As you can see this webapp will have 5 pages, one for the index, 3 for 3 different sounds (wave, rain and whitenoise) and 1 more to stop. All 4 non-index pages redirect back to index ('/') after they execute the command sent to omxplayer, so we only need to create one index.html, and nothing else. I'm using killall here as a stop function, because I couldn't find a better way to send a "stop" command to omxplayer. If you know of a better way of doing this, I'd love to hear it!

Now let's put together the index.html.

Step 8: Building the Website

These are the images I used for my build, but feel free to make your own. They all need to be saved in the static folder we made earlier. The index.html file we're going to make here needs to be in the templates folder. That's pretty important, otherwise, none of it will work. Here is the code for my index.html (again, this is just simple html, so modify it in whatever way works for you).

Since Instructables won't let me post raw HTML, here is a link to the file as it exists on my Dropbox:


But in case that ever dies, the HTML file is just some fancy CSS, and a simple 2x2 table with those 4 icons as buttons with post values like so:

form action="/whitenoise" method="post"
  input type="image" src="/static/whitenoise.png" value="White Noise"

Should be pretty easy to make yourself one.

Last step is to make sure the webapp.py runs at startup, again, I did this by adding it to the crontab. So once again type crontab -e and add the following to the end:

@reboot python3 /home/pi/www/webapp.py

Then reboot the pi, point a browser on another machine (your phone) to the IP of the pi (best if you can make this static) and see if it worked. Click the buttons and see if you get noise.

On an Android phone you can bookmark a website to your homescreen, which is what I did with this to get it to look and feel like an app. If you want to really make it look "pro" find or create a suitable .ico file and give the website its own icon which will appear on your phone's home screen and look much more like an app. Lots of tutorials online on how to add an icon (favicon) to a website.

Step 9: Jam Everything in to a Case

Now that everything has been tested and is working, time to stuff it all in to a case.

I built a standoff mount for the Raspberry Pi Zero using some leftover plastic I had around the house. I then drilled some holes for the panel mount micro USB, and using some jewelers files squared off the hole. The panel mount cable is a bit stiff, so I may buy a right angle adapter for the micro USB port on the Pi sometime in the future.

I cut a small opening in the top of the case for the speaker to play out through by drilling two holes and connecting them with a Dremel. Then drilled the holes in the lid to mount the Speaker Phat. For what it's worth, after taking this photo I went back and made a few more holes because the noise was really getting trapped inside the case. I mounted the Blinkt using that poster putty stuff because the thing doesn't have any mount holes, but the putty seems to hold well, so it'll do.

Step 10: That's It!

Plug it in and you're done. Here's mine running just after 8pm. The green LED on the pi itself isn't as bright as this photo makes it appear.

Some later edits I made:

I added 4 more pages to the webapp.py and index.html files. Those 4 being "red", "yellow", "green", and "off". Pretty self explanatory. I wanted the ability to switch it from green back to yellow if the wife and I were feeling extra tired and didn't want to be bothered.

@app.route('/red', methods = ['POST'])	
def red(): os.system("python ~/scripts/red.py") return redirect('/')

Basically that 4 times, running the 4 different scripts, then some more buttons in index that call those pages.

The other change I already noted, but I drilled some more holes and widened the existing opening around the speaker because the noise wasn't escaping the enclosure well enough.

If I make any additional modifications, I'll be sure to come back here and list them.

Step 11: Addendum

After building this I realized that my wife and I both frequently leave our phones downstairs when putting the kid down for bed or a nap. So I added a momentary push button to physical pin 36, and included the following code (I called it button.py) to run at startup in rc.local:

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
import os
import subprocess
import re

GPIO.setmode(GPIO.BOARD)   # Use Physical Pin Numbering Scheme
button=36                  # Button is connected to physical pin 16

GPIO.setup(button,GPIO.IN,pull_up_down=GPIO.PUD_UP) # Make button an input, Activate Pull UP Resistor

while True:
  if GPIO.input(button)==0:			# Wait for button press
    returnprocess = False			# Initially set to sound being off
    s = subprocess.Popen(["ps", "ax"],stdout=subprocess.PIPE)
    for x in s.stdout:
      if re.search("mpg123", x):
        returnprocess = True

    if returnprocess == False:
      os.system("mpg123 --loop -1 /home/pi/scripts/sounds/whitenoise.mp3 &")
      os.system("python /home/pi/scripts/red.py")

      os.system("killall mpg123")
      os.system("python /home/pi/scripts/lightsout.py")

As you can see, I also switched to mpg123 from omxplayer because it's much more lightweight and simple to use.

HOWEVER, for some reason when I put this script in rc.local it does indeed run at startup without any problems. But the audio is really really choppy. When I run the script as normal, in putty, no such issues. I'm having a bear of a time troubleshooting this, so if anyone has any ideas, please let me know! Thanks.

1 Person Made This Project!


  • Build a Tool Contest

    Build a Tool Contest
  • Make It Modular: Student Design Challenge

    Make It Modular: Student Design Challenge
  • Digital Fabrication Student Design Challenge

    Digital Fabrication Student Design Challenge



Question 1 year ago on Step 2

I am a total noob who bought a Raspberry pi B+ long time ago,and I am know a father with two questions:
First : how I know where to connect the 4 cables on the Blinkt?
Second: Since I am the kind of noob who bought before thinking, I bought a phatBeat instead of the speakerBEAT (which is not available). Problem is that according to https://pinout.xyz/ Blinkt and PhatBeat need to be both connected to BCM23 and BCM24, so my question is : Is it possible to connect the blinkt to BCM27 and BCM22?


Answer 1 year ago

Not without a lot of work. You have a few options though, you dont have to use the speakerPhat. Pimoroni makes a board called a PhatDAC (digital to analog converter) which is overkill, but it will output audio with a traditional headphone jack. That means you'll need a speaker to plug in, but those can be found for pretty cheap on amazon.
Check pimoroni's website for the curl command to get the DAC installed and working, and really that should be the only thing you need to change for the project. Feel free to write back if you run in to any issues. Happy to help!


2 years ago

I don't have any kids at home anymore, but sure could use the restfulness of the white noise for my wife and I to go to sleep. Any way to just have this be a white noise generator without the lites?


Reply 2 years ago

Yea you can absolutely do that. But you can get a generic white noise machine on Amazon for like $14, which is much cheaper that this project. Unless you really want to get your build on, then go nuts.


2 years ago

Aww dude that is cheating! You should have to deal with early morning wake-ups like the rest of us have since the dawn of parenting! :-) (pun intended) HAHAHA!

But seriously, I LOVE IT! I might try and make one of these for my son. He is older now but has a mild case of tinnitus so he usually leaves a fan on at night. I am not good with coding stuff at all so I might have to get his younger brother to help me, that is his thing.

Great idea - thanks for sharing!


Question 2 years ago on Step 11

Hi there, I just finished following your project - great idea BTW! - I too am getting choppy audio since adding the physical button and associated code. Did you ever manage to fix it?

Answer 2 years ago

Unfortunately no. But I'm still poking around trying different things. As soon as I get it to work, no matter how kludgy it is, i'll post it here.


Question 3 years ago on Step 8

Hi, great tutorial. Just wondering two things: have you found another way of disabling the pHAT's lights? This didn't work for me. Secondly, I have the website up and running. The first click of a button starts the correct white noise running, but all subsequent button presses do nothing (inc. stop) and ctrl+c in terminal kills the webapp but the omxplayer continues until I issue a killall. Any ideas what's going wrong? Thanks


Reply 3 years ago

So the lights on the Speaker pHAT are called the VU Meter. Are you 100% sure the /etc/asound.conf file is moved or renamed? I googled "disable VU Meter on Speaker pHat" and got a few results, those might help. One suggestion was to run the following after renaming or deleting the /etc/asound.conf file; "sudo systemctl restart pulseaudio"
As for the noises, they will just play over top of each other if you don't stop them in between (I had thought about calling the killall command from the stop button before each sound, but sometimes I like layering whitenoise and rain). If stop isn't working, test to see that the command actually works. After starting a sound, in the SSH terminal run "killall omxplayer.bin" if nothing happens, then there's a problem.
If ctrl+c is killing the webapp, when you run it from the terminal, put an ampersand '&' after the command "python3 webbapp.py &" that should run it in the background and drop you back to the terminal.
Hope that helps. Let me know how it goes. Good Luck!


Reply 3 years ago

Thanks I'll give it a whirl. I was having an issue where the web server was still.connected after the app was terminated, but I think I've got that covered. Thanks for the quick response!