Voice-Controlled
AI Home Assistant
Build an intelligent smart home voice assistant using Raspberry Pi Pico and MicroPython — with OLED display, DHT22 sensor, multi-room LED control, and buzzer audio feedback.
🔬 No hardware needed — run the full project free in your browser
▶ Open Free Wokwi SimulationWhat You'll Build
A simplified AI assistant that listens to commands, controls smart home devices, reads sensor data, and displays responses on an OLED screen — all running on a Raspberry Pi Pico.
Wake Word
Activates on "Hey Assistant" — just like Alexa or Google Home
3-Zone Lighting
Control living room, bedroom, and kitchen lights independently
DHT22 Sensor
Real-time temperature and humidity readings on demand
OLED Display
SSD1306 128×64 shows commands and responses visually
Audio Feedback
Buzzer simulates text-to-speech with short, long, and alert tones
State Machine
Idle → Listening → Processing — real AI assistant architecture
Smart Routines
"Good Morning" turns all lights on, "Goodnight" shuts everything off
Wokwi Ready
Fully simulated in Wokwi — no hardware needed to get started
Key Features
Everything this assistant can do
Wake Word + Command Recognition
The assistant activates on "Hey" or "Assistant" and then processes the next spoken command using keyword-based NLP parsing. Commands are matched against known patterns for device control, sensor queries, and routines.
3-Zone LED Device Control
Three LEDs represent the living room (red), bedroom (green), and kitchen (blue). Each can be individually toggled or all controlled at once. Device states are tracked in a dictionary for status reporting.
DHT22 Temperature & Humidity
Reads live temperature (°C) and humidity (%) from the DHT22 sensor. Responds to natural queries like "What's the temperature?" or "What's the weather?" and displays readings on the OLED.
Idle → Listening → Processing State Machine
The assistant uses a three-state machine: Idle (showing standby screen), Listening (activated by wake word or button), and Processing (executing commands and updating the OLED). This mirrors real AI assistant design.
Components Required
All available as virtual parts in Wokwi — or build on real hardware!
Raspberry Pi Pico
Main microcontroller running MicroPython firmware — manages all peripherals and game logic
SSD1306 128×64 I2C OLED Display
Shows boot screen, listening indicator, command responses, and sensor readings
DHT22 Temperature & Humidity Sensor
Provides real-time environment data — responds to temperature and humidity voice queries
3× LEDs (Red / Green / Blue)
Represent smart devices: Living Room (red), Bedroom (green), Kitchen (blue)
Active Buzzer
Produces short, long, and alert tones to simulate text-to-speech audio feedback
Push Button (WAKE)
Physical wake trigger — press to activate the assistant without typing the wake word
3× 220Ω Resistors
Current-limiting resistors — one in series with each LED
Breadboard + Jumper Wires
For physical builds — all connections are pre-wired in the Wokwi simulation
Pin Wiring Reference
All GPIO connections for Raspberry Pi Pico
| Component | Pico Pin | Notes |
|---|---|---|
| OLED SDA | GP0 | I2C data |
| OLED SCL | GP1 | I2C clock |
| OLED VCC | 3V3 | 3.3V power |
| DHT22 SDA | GP15 | Data signal |
| LED Living Room | GP10 | 220Ω series |
| LED Bedroom | GP11 | 220Ω series |
| LED Kitchen | GP12 | 220Ω series |
| 🔊 Buzzer (+) | GP13 | (−) to GND |
| 🟢 Wake Button | GP14 | PULL_UP, active LOW |
0x3C by default. The Pico uses I2C bus 0 with GP0 (SDA) and GP1 (SCL) at 400 kHz.
Pin.PULL_UP internally — no external resistor needed. Button reads 0 when pressed, 1 when released.
diagram.json
Paste this into Wokwi to auto-load the full circuit in seconds
Open Wokwi
Go to wokwi.com → New Project → Raspberry Pi Pico. Log in with Google to save and share your project.
Paste diagram.json
Click the diagram.json tab → select all (Ctrl+A) → delete → paste the JSON below → Ctrl+S to save.
Paste main.py
Switch to the main.py tab → paste the full MicroPython code → click ▶ Play to start the simulation.
Test via Serial Monitor
Open the Serial Monitor tab → type Hey Assistant to wake it, then type a command like turn on living room.
{
"version": 1,
"author": "Voice Assistant Project",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-pi-pico", "id": "pico", "top": 0, "left": 0, "attrs": {} },
{
"type": "wokwi-ssd1306", "id": "oled1",
"top": -137.33, "left": 122.67,
"attrs": { "i2cAddress": "0x3C" }
},
{
"type": "wokwi-dht22", "id": "dht1",
"top": -145.2, "left": -115.2, "attrs": {}
},
{
"type": "wokwi-led", "id": "led_red",
"top": 120, "left": -180,
"attrs": { "color": "red", "label": "Living Room" }
},
{
"type": "wokwi-led", "id": "led_green",
"top": 120, "left": -100,
"attrs": { "color": "green", "label": "Bedroom" }
},
{
"type": "wokwi-led", "id": "led_blue",
"top": 120, "left": -20,
"attrs": { "color": "blue", "label": "Kitchen" }
},
{ "type": "wokwi-resistor", "id": "r1", "top": 110, "left": -210, "attrs": { "value": "220" } },
{ "type": "wokwi-resistor", "id": "r2", "top": 110, "left": -130, "attrs": { "value": "220" } },
{ "type": "wokwi-resistor", "id": "r3", "top": 110, "left": -50, "attrs": { "value": "220" } },
{
"type": "wokwi-buzzer", "id": "buzzer1",
"top": 90, "left": 100,
"attrs": { "volume": "0.8" }
},
{
"type": "wokwi-pushbutton", "id": "btn1",
"top": -60, "left": -220,
"attrs": { "color": "green", "label": "WAKE" }
}
],
"connections": [
["pico:GP0", "oled1:SDA", "green", ["v0"]],
["pico:GP1", "oled1:SCL", "blue", ["v0"]],
["pico:3V3(OUT)", "oled1:VCC", "red", ["v0"]],
["pico:GND.8", "oled1:GND", "black", ["v0"]],
["pico:3V3(OUT)", "dht1:VCC", "red", ["v0"]],
["pico:GND.3", "dht1:GND", "black", ["v0"]],
["pico:GP15", "dht1:SDA", "orange", ["v0"]],
["pico:GP10", "r1:1", "red", ["v0"]],
["r1:2", "led_red:A", "red", ["v0"]],
["led_red:C", "pico:GND.4", "black", ["v0"]],
["pico:GP11", "r2:1", "green", ["v0"]],
["r2:2", "led_green:A", "green", ["v0"]],
["led_green:C", "pico:GND.5", "black", ["v0"]],
["pico:GP12", "r3:1", "blue", ["v0"]],
["r3:2", "led_blue:A", "blue", ["v0"]],
["led_blue:C", "pico:GND.6", "black", ["v0"]],
["pico:GP13", "buzzer1:1", "magenta", ["v0"]],
["buzzer1:2", "pico:GND.7", "black", ["v0"]],
["pico:GP14", "btn1:1.l", "yellow", ["v0"]],
["btn1:2.l", "pico:GND.2", "black", ["v0"]]
],
"dependencies": {}
}
MicroPython Code
Full main.py — paste into Wokwi's editor
① Imports & Pin Setup
from machine import Pin, I2C, ADC import time, framebuf, dht # I2C + OLED i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000) oled = SSD1306_I2C(128, 64, i2c) # DHT22 Sensor dht_sensor = dht.DHT22(Pin(15)) # Smart device LEDs led_living = Pin(10, Pin.OUT) led_bedroom = Pin(11, Pin.OUT) led_kitchen = Pin(12, Pin.OUT) # Buzzer + Wake button buzzer = Pin(13, Pin.OUT) wake_button = Pin(14, Pin.IN, Pin.PULL_UP) # Device state dictionary devices = { "living_room": False, "bedroom": False, "kitchen": False } temperature = 0.0 humidity = 0.0 listening = False
② speak() — Audio + OLED Output
def speak(message, tone_pattern="short"): """Display on OLED + buzzer audio feedback""" print(f"🔊 Assistant: {message}") oled.fill(0) oled.rect(0, 0, 128, 64, 1) oled.text("ASSISTANT", 30, 5) # Word-wrap message to 16-char lines words = message.split() lines, line = [], "" for word in words: if len(line + word) < 16: line += word + " " else: lines.append(line.strip()); line = word + " " if line: lines.append(line.strip()) y = 25 for l in lines[:4]: oled.text(l, 5, y); y += 10 oled.show() # Buzzer tones if tone_pattern == "short": buzzer.on(); time.sleep(0.1); buzzer.off() elif tone_pattern == "long": for _ in range(2): buzzer.on(); time.sleep(0.15) buzzer.off(); time.sleep(0.05) elif tone_pattern == "alert": for _ in range(3): buzzer.on(); time.sleep(0.05) buzzer.off(); time.sleep(0.05) time.sleep(2)
③ process_command() — Voice NLP Parser
def process_command(command): cmd = command.lower().strip() if "living" in cmd: if "on" in cmd: led_living.on(); devices["living_room"] = True speak("Living room on", "short") elif "off" in cmd: led_living.off(); devices["living_room"] = False speak("Living room off", "short") elif "bedroom" in cmd: if "on" in cmd: led_bedroom.on(); devices["bedroom"] = True speak("Bedroom on", "short") elif "off" in cmd: led_bedroom.off(); devices["bedroom"] = False speak("Bedroom off", "short") elif "kitchen" in cmd: if "on" in cmd: led_kitchen.on(); devices["kitchen"] = True speak("Kitchen on", "short") elif "off" in cmd: led_kitchen.off(); devices["kitchen"] = False speak("Kitchen off", "short") elif "all" in cmd: state = "on" in cmd led_living.value(state); led_bedroom.value(state) led_kitchen.value(state) for k in devices: devices[k] = state speak(f"All lights {'on' if state else 'off'}", "long") elif "temperature" in cmd or "weather" in cmd: dht_sensor.measure() temperature = dht_sensor.temperature() humidity = dht_sensor.humidity() speak(f"{temperature}C {humidity}%", "short") elif "time" in cmd: t = time.localtime() speak(f"{t[3]}:{t[4]:02d}", "short") elif "good morning" in cmd or "morning" in cmd: led_living.on(); led_bedroom.on(); led_kitchen.on() for k in devices: devices[k] = True speak("Good morning!", "long") elif "goodnight" in cmd or "good night" in cmd: led_living.off(); led_bedroom.off(); led_kitchen.off() for k in devices: devices[k] = False speak("Goodnight!", "long") elif "status" in cmd: count = sum(devices.values()) speak(f"{count} devices on", "short") elif "help" in cmd: speak("Say turn on/off device", "long") else: speak("Not understood", "alert")
④ Main Loop — State Machine
show_boot_screen() update_temperature() show_idle_screen() try: while True: # Physical wake button (active LOW) if wake_button.value() == 0: listening = True show_listening_screen() speak("Yes?", "short") while wake_button.value() == 0: time.sleep(0.1) # Serial input simulates voice (for Wokwi) user_input = input("🎤 You: ").strip() if listening else "" if user_input: if "hey" in user_input.lower() or "assistant" in user_input.lower(): listening = True show_listening_screen() speak("Yes?", "short") elif listening: process_command(user_input) listening = False show_idle_screen() else: time.sleep(0.1) except KeyboardInterrupt: led_living.off(); led_bedroom.off(); led_kitchen.off() buzzer.off() oled.fill(0); oled.text("GOODBYE!", 35, 28); oled.show()
Supported Voice Commands
Type these in the Wokwi Serial Monitor after saying "Hey Assistant"
💡 Device Control
🌡️ Information Queries
⏰ Smart Routines
Hey Assistant → press Enter → the OLED shows "LISTENING..." → then type your command e.g. turn on all lights → press Enter.
What You Will Learn
Key programming and electronics concepts covered by this project
Keyword-Based Command Matching
Commands are parsed by checking whether keywords like "living", "on", or "temperature" appear in the lowercased input string. This is how simple NLP worked before large language models — fast, lightweight, and perfect for microcontrollers.
Idle → Listening → Processing
The listening boolean flag controls which branch of the main loop runs. This is a classic embedded state machine — the device behaves completely differently based on its current state. Real AI assistants like Alexa use a much more complex version of this same pattern.
OLED Display via I2C Protocol
The SSD1306 OLED communicates over I2C using just two wires (SDA + SCL). The custom driver writes display commands and pixel data via i2c.writeto(). Understanding I2C is essential for connecting sensors, displays, and modules in embedded systems.
DHT22 Temperature & Humidity
The DHT22 sensor uses a single-wire protocol. Calling dht_sensor.measure() triggers a reading, then .temperature() and .humidity() return the values. Sensor errors are caught with a try/except so the system continues running even if a reading fails.
Synchronized Smart Home Logic
All three LEDs share a devices dictionary that tracks on/off state. This lets the "Status" command count active devices, and lets routines like "Good Morning" and "Goodnight" update all lights and their states in a single block of code.
Comments
Post a Comment