What You'll Need
Control your home devices from your phone or laptop using this simple, budget-friendly DIY project. We'll build a web-based controller using a Raspberry Pi Zero W, MOSFET switches, and a custom web console—no cloud services required.
Hardware
- Raspberry Pi Zero W (with 40-pin GPIO header)
- 12V DC power adapter (for connected loads)
- 2x Logic-level N-channel MOSFETs (e.g., IRL44N)
- 2x 10kΩ resistors (gate pull-down)
- 2x LEDs (optional, for status indication)
- 2x 330Ω resistors (for LEDs, if used)
- Breadboard and jumper wires
- MicroSD card (8GB or larger)
- Micro USB power supply (5V, 2.5A recommended for Pi)
Tools
- Soldering iron and solder (if making a PCB)
- Wire strippers
- Screwdriver (for terminal blocks, if used)
Software
- Raspberry Pi OS (installed on SD card)
- Python 3 (pre-installed on Raspberry Pi OS)
- Flask library for Python
Step-by-Step Guide
Step 1: Understand the Circuit Design
The heart of this project is the Raspberry Pi Zero W, which controls two MOSFET switches via GPIO pins 23 and 24. Here's how the power flows:
- 12V rail: Powers your connected devices (LED strips, fans, pumps, etc.)
- 5V rail: Powers the Raspberry Pi (via USB or a voltage regulator)
- 3.3V logic: The Pi's GPIO pins output 3.3V—never connect 5V directly to a GPIO pin
The MOSFETs act as electronic switches. When the Pi sends a HIGH signal (3.3V) to the gate, the MOSFET turns on and completes the circuit for your 12V device. A 10kΩ resistor between the gate and ground keeps the MOSFET off when the GPIO is not actively driven.
Safety warning: Always double-check your wiring before connecting power. A wrong connection can damage your Pi or MOSFETs.
Step 2: Build the Circuit on a Breadboard
Start by setting up the circuit on a breadboard to test everything before making it permanent.
- Place the Raspberry Pi Zero W on the breadboard (use female headers if available)
- Connect the 5V pin on the Pi to the positive rail of the breadboard
- Connect a ground pin on the Pi to the negative rail
- For each MOSFET:
- Connect the gate to a GPIO pin (23 or 24) through a 10kΩ resistor to ground
- Connect the drain to the negative terminal of your 12V device
- Connect the source to ground (common with Pi ground)
- Connect the positive terminal of each 12V device to the 12V power supply positive
- Connect the 12V power supply ground to the breadboard ground rail
If using status LEDs:
- Connect each LED in series with a 330Ω resistor between the GPIO pin and ground
- The LED will light up when the GPIO goes HIGH
Step 3: Set Up the Raspberry Pi
- Flash Raspberry Pi OS onto your microSD card using the Raspberry Pi Imager tool
- Insert the SD card into the Pi Zero W
- Connect the Pi to power via the micro USB port
- Follow the on-screen setup to connect to Wi-Fi and enable SSH (optional)
Pro tip: Enable SSH during the initial setup so you can control the Pi from your computer without connecting a monitor and keyboard.
Step 4: Test the GPIO Pins
Before building the web interface, confirm your wiring works. Create a test script:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)
# Turn on pin 23 for 2 seconds
GPIO.output(23, GPIO.HIGH)
time.sleep(2)
GPIO.output(23, GPIO.LOW)
# Turn on pin 24 for 2 seconds
GPIO.output(24, GPIO.HIGH)
time.sleep(2)
GPIO.output(24, GPIO.LOW)
GPIO.cleanup()
Save this as `test_pins.py` and run it with `python3 test_pins.py`. You should see your connected devices turn on and off in sequence.
Step 5: Install Flask on the Pi
Open a terminal on your Pi and install Flask:
sudo apt update
sudo apt install python3-pip
pip3 install flask
Step 6: Create the Web Control Interface
Now we'll build a small web server that serves a control panel. Create a new file called `web_control.py`:
from flask import Flask, render_template_string, request, redirect
import RPi.GPIO as GPIO
app = Flask(__name__)
# Define your GPIO pins
PINS = [23, 24]
pin_states = {23: False, 24: False}
# Setup GPIO
GPIO.setmode(GPIO.BCM)
for pin in PINS:
GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, GPIO.LOW)
HTML_TEMPLATE = """
body { font-family: Arial; text-align: center; padding: 20px; }
.device { margin: 20px; padding: 20px; border: 1px solid #ccc; border-radius: 10px; }
.on { background-color: #4CAF50; color: white; }
.off { background-color: #f44336; color: white; }
button { padding: 15px 30px; font-size: 18px; margin: 10px; cursor: pointer; }
Home Automation Controller
{% for pin in pins %}
Device on GPIO {{ pin }}
Status: {{ 'ON' if states[pin] else 'OFF' }}
{% endfor %}