Introduction: Ad-blocking Neopixels

I wanted to make a simple website as remote for a strip of
neopixels connected to my Raspberry Pi zero and keep using it to block ads on my network using Pi-Hole. First I just wanted to add some leds in my room, but wiring everything up I realised I had no way to conveniently control them. So I decided to create a simple website with some basic control options using the apache server the Pi-hole installer already set up. I granted www-data root permissions, which is a security risk, so you should pronbably make the webserver not available to the outside world. This started mainly for my own documentation and than somehow became my first instructable ;) So I would really appreciate if you could point out If something is unclear or if I completely missed something.

Step 1: Used Materials

  • Raspberry Pi (I started on a Pi 2 and then changed to the WH, the gpio pins might be slightly different but otherwise every model is fine)
    • If you have a RPi without built in wifi, a wifi adapter is usefull too.
    • Optionally a case for the raspberry pi
  • 2 Male-female jumper wires (for example)
  • Neopixels ws2811 (I used these)
  • 1 10W power supply for the RPi (An old phone charger will do)
  • 1 ~50W power supply for the Neopixels (I used one like this, but probably a smaller one would suffice, but if you would like more leds, you have some room left to expand.)
  • Female jack connector plug (like this)

Step 2: Prepare the Operating System

Download the latest version Rasbian from raspberrypi.org The lite version is fine for this project, if you plan to use the raspberry pi for something else as well you might consider installing the full version with gui.
Then I burned the image with Etcher. After that to make sure it will connect with my wifi network I added wpa_supplicant.conf in the boot directory of sd card. The content of the file should look like this:

~~~

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1

network={

ssid="SSID"

psk="PASSWORD"

key_mgmt=WPA-PSK }

~~~

To enable ssh I created a file called ssh (without any extension) in the same directory. This will make sure your able to configure everyting from another computer in your lan.

Step 3: Connecting the Neopixels

First I plugged the power supply in the female jack connector and put the RPi in a case. I screwed the ground cable from the leds (the blue cable) and a male side of a jumper wire in negative side of the jack connector. The other end of the jumper wire I did connect to a ground pin on the gpio header, I used pin 6 but the exact pins you can use will depend on the exact model RPi you're using.


Secondly I connected on the positive end of the jack connector the 5v cable from the leds (the red cable). On my led their was a jumper wire connector on an additional ground cable and the data cable (the white cable). I just ignored the additional ground cable, it was unnecessary for my setup. On the data cable I connected a male to female jumper wire with the gpio pin 12, again the exact pin you should use depends on your RPi. Then I plugged in my power supply for the RPi and the pixels. The leds did light up for a short moment, if everything is wired correctly.

Step 4: Start the RPi

Afther giving the RPi a minute or so to boot up, I looked up the IP adress from the raspberry with nmap. But any network scanner, the information panel of your router or in most cases simply "raspberrypi.local" will do. With that information I connected with RPi through ssh.
The default user is pi with the password raspberry. So that's the first thing I changed using `passwd` directly after the first login. If you would like to access your pi through ssh from outside your local network, you should look into fail2ban and key authentication. I personally don't have a use case for that, so I will leave it with just a password.

Secondly I updated the software using `sudo apt update && sudo apt upgrade -Y`. I also needed some additional software to compile the libery `sudo apt-get install scons swig git python-dev build-essential -Y`. Then I copied the excellent libery from Jeremy Garff on github `git clone https://github.com/jgarff/rpi_ws281x.git`. After that the libery was cloned I went to the rpi_ws281x directory, used scons and then installed the libary with `sudo python python/setup.py install`. In python/examples is a nice demo "strandtest.py" with really neat animations which you can start with `sudo python python/examples/strandtest.py`.

Step 5: Pi-Hole

To create a network wide add blocker, Pi-Hole is perfect. It installs with just `sudo curl -sSL https://install.pi-hole.net | bash`. The nice part is that it will set-up an web server as well.

After running the installer you will want to log in to the admin site of your router and give your RPi a static IP-adress and set it up as the DHCP Server. If you have set a low lease time than your PI-hole should work now.

Step 6: Control the Lights

The easiest way to control the neopixels is with small python programs. But to use ssh each and every time you want to turn the lights on is inconvenient, especially on a mobile device. So I decided to use a small website as remote control. THIS IS A SECURITY RISK, because I gave the www-data root permission without password verification. You probably should not make this site available outside your lan.


To make it easy to choose between the dashboard of PI-hole and the light remote, I gave the user pi write access to /var/www/html with `sudo chown -R pi /var/www.html` and I created an index.php file in /var/www/html/. Something simple like:

~~~

< ?php ?>
< html> < b>Index < /b>
< a href="/admin">Pi hole < /a>
< a href="/lights">Light remote < /a>< /html>

~~~

is fine. Then I created a new folder called lights to have everything from the neopixels together. Here I created colour.py based on the strandtest.py from the libery.

~~~

from neopixel import * # Import some libraries

import sys

def led(strip, color, start, end): # Create a function to call leds

for i in range(start, end):

strip.setPixelColor(i, color)

strip.show()

BRIGHTNESS = int(sys.argv[4]) # The fourth parameter on the commandline will be brightness. (1-255)

COUNT = 50 # The amount of leds PIN = 12 # The pin used on the RPi

FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)

DMA = 5 # DMA channel to use for generating signal (try 5)

INVERT = False # True to invert the signal (when using NPN transistor level

strip = Adafruit_NeoPixel(COUNT, PIN, FREQ_HZ, DMA, INVERT, BRIGHTNESS)

strip.begin()

R = int(sys.argv[1]) # The amount of red is the first parameter

G = int(sys.argv[2]) # The amount of green is the second paramter

B = int(sys.argv[3]) # The amount of blue is the third parameter

try:

leds(strip, Color(R,G,B), 0,49) #Will start the lets with the choosen color and brightness.

except KeyboardInterrupt:

color(strip, Color(0,0,0), 0, 49)

~~~

If you run this with sudo on the terminal the lights should go on in the color specified. To give www-data sudo permission I added `www-data ALL=(ALL) NOPASSWD:ALL)` to the sudoers file (/etc/sudoers) directly under the root user.

Step 7: Turn the Lights on With the Browser

Then I created anonther index.php, this time in /lights.
~~~

< ?php
$R = 100; $G = 100; $B = 100; $BRIGHTNESS = 100; exec("sudo python colour.py $R $G $B $BRIGHTNESS"); ?>

~~~

When I now visit raspberrypi.local/lights/index.php the leds will turn white. Though this is a nice start, I like to have at least some buttons on a remote.

Step 8: Control the Lights From the Browser

I created an interface with buttens using a html form. I dislike doing things that are not needed, so I created an folder called templates with my header, footer and the main php code.
My (for now) final /lights/index.php looks like this:

~~~
< ?php include "templates/BasicControl.php"; include "templates/header.php"; ?>

< form method="post" class="buttons">

< input class="buttons_index" type="submit" name="strandtest_start" value="STRANDTEST START">

< input class="buttons_index" type="submit" name="strandtest_stop" value="STRANDTEST STOP">

< input class="buttons_index" type="submit" name="red" value="RED">

< input class="buttons_index" type="submit" name="green" value="GREEN">

< input class="buttons_index" type="submit" name="blue" value="BLUE">

< input class="buttons_index" type="submit" name="white" value="WHITE">

< input class="buttons_index" type="submit" name="off" value="OFF">

< input class="buttons_index" type="submit" name="reboot" value="REBOOT"> < /form>

< ?php include "templates/footer.php"; ?>

~~~

To make the buttons work I made a template BasicControl.php. In this I specified the code that should be executed when a button is pressed. Because I liked the strandtest animations I included that one as well. The strandtest will continue infinit long, so I made another button to stop the proces whenever I want.

~~~
< ?php

$I = 100;

$R = 0;

$G = 0;

$B = 0;

if (isset($_POST['strandtest_start'])) { exec("sudo python strandtest.py"); }

else if (isset($_POST['strandtest_stop'])) { exec("sudo pkill -9 -f strandtest.py"); }

else if (isset($_POST['red'])) { $R = 255; $G = 0; $B = 0; exec("sudo python colour.py $R $G $B $I"); }

else if(isset($_POST['green'])) { $R = 0; $G = 255; $B = 0; exec("sudo python colour.py $R $G $B $I"); }

else if(isset($_POST['blue'])) { $R = 0; $G = 0; $B = 255; exec("sudo python colour.py $R $G $B $I"); }

else if(isset($_POST['white'])) { $R = 255; $G = 255; $B = 255; exec("sudo python colour.py $R $G $B $I"); }

else if(isset($_POST['off'])) { shell_exec('sudo python off.py'); }

else if(isset($_POST['reboot'])) { shell_exec('sudo reboot now'); } ?>

~~~

Step 9: Create a Template for the Header and Footer

Now it all works, but it isn't too pleasant to look at. After importing the header and footer all elements of the site are available, just not styled.

Header.php:

~~~
< html>

< head>

< title>Lights

< link rel="stylesheet" href="style.css">

< meta name="viewport" content="width=device-width, initial-scale=1.0">

< ?xml version="1.0" encoding="utf-8"?>

< body>

< div class="header">

< H1> Lampjes

< /div>

< div class="navbar">

< a href="index.php" class="HeaderLinks">Basic Controls < /A>

< a href="advanced.php" class="HeaderLinks">Advanced Controls

< /div>

~~~

And the footer.php:

~~~
< div class="footer">

< /div>

< /body>

< /html>

~~~

Step 10: Some Css to Make It All Look a Bit Better

As you might have noticed, I'm using an css file to control the layout. To make sure my remote is usable on smaller screens as well I used some css flexboxes with autowrap.


~~~

/* Stylesheet for the light control interface *

* Applies on every page */

body { background-color: f9fcfa; font-family: Arial; margin: 0; }

h1 { color: white; text-align: center; }

p { font-family: verdana; font-size: 20px; }

h2 { }

/* The header */

.header { height: 10%; display:flex; justify-content:flex-start; align-items:center; margin: 0px; padding-left: 5%; background:#3F51B5; align-items: center; }

.HeaderLinks { color: white; }

.navbar { display: flex; flex:30%; justify-content:space-around; background-color: #3F51B5; color: white; }

/* The footer */

.footer { background-color: #3F51B5; height: 10%; text-align: center; }

/* Index.php */

.buttons { display:flex; flex-direction: row; flex-wrap: wrap; justify-content:space-between; height: 80%; align-items:flex-start; }

.buttons_index { padding:0%; border-width: thin; border-style: solid; border-color: black; background-color: #3949ab; color: white; font-family: sans-serif; width: 24%; height: 20%; }

.buttons_index:hover{ padding:0%; border-width: thin; border-style: solid; border-color: black; background-color: #536DFE; color: white; font-family: sans-serif; width: 24%; height: 20%; }

~~~

Step 11: Thank You

And that's it. Everything works for me and I hope it will work for you too if choose try my instructable. If you tried to copy some code, I had to add a few spaces for uploading it here, so you will have to delete them before the code becomes useful again.

I hope you enjoyed reading everything. If you have feedback, I would love to hear it!