Voice Assistant offline tiếng Việt với Raspberry Pi
Nâng cao✦ Nổi bật1/3/2026

Voice Assistant offline tiếng Việt với Raspberry Pi

Xây dựng trợ lý giọng nói offline hoàn chỉnh bằng Vosk + Raspberry Pi để điều khiển nhà thông minh không cần internet.

Raspberry PiVoskMQTTGPIOPythonVoiceIoT
0 lượt thích0 người đã làm5 giờ5 bước5 linh kiện
← Quay lại dự án
Hướng dẫn chi tiết

Bài 4: Điều khiển relay GPIO và phản hồi giọng nói (TTS)

Kết nối module relay 4 kênh vào GPIO, viết gpio_controller.py và tts.py, test bật/tắt thiết bị thực tế bằng lệnh giọng nói.

Cập nhật 04/03/2026

Sơ đồ kết nối Relay 4 kênh → Raspberry Pi 4

Relay Module    Raspberry Pi 4 (BCM)
─────────────────────────────────────
VCC        →   Pin 2  (5V)
GND        →   Pin 6  (GND)
IN1        →   GPIO17 (Pin 11) — Đèn
IN2        →   GPIO27 (Pin 13) — Quạt
IN3        →   GPIO22 (Pin 15) — Điều hòa
IN4        →   GPIO23 (Pin 16) — Ổ cắm
Module relay 5V thường active-LOW: GPIO LOW → relay kích (thiết bị BẬT).

gpio_controller.py

import RPi.GPIO as GPIO
from config import DEVICE_PINS

ACTIVE_LOW  = True
_initialized = False

def init() -> None:
    global _initialized
    if _initialized: return
    GPIO.setmode(GPIO.BCM); GPIO.setwarnings(False)
    for pin in DEVICE_PINS.values():
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.HIGH if ACTIVE_LOW else GPIO.LOW)
    _initialized = True

def set_device(device: str, state: bool) -> bool:
    pin = DEVICE_PINS.get(device)
    if pin is None: return False
    GPIO.output(pin, (GPIO.LOW if state else GPIO.HIGH) if ACTIVE_LOW
                     else (GPIO.HIGH if state else GPIO.LOW))
    print(f"[GPIO] {'BẬT' if state else 'TẮT'} {device} (GPIO{pin})")
    return True

def get_states() -> dict[str, bool]:
    return {d: (GPIO.input(p)==GPIO.LOW if ACTIVE_LOW else GPIO.input(p)==GPIO.HIGH)
            for d, p in DEVICE_PINS.items()}

def cleanup() -> None:
    GPIO.cleanup()

tts.py

import subprocess
from config import DEVICE_NAMES_VI

def speak(text: str, speed: int = 150) -> None:
    subprocess.run(["espeak-ng","-v","vi","-s",str(speed),text],
                   capture_output=True, timeout=15)

def announce_command_result(device: str, state: bool) -> None:
    name = DEVICE_NAMES_VI.get(device, device)
    speak(f"Đã {'bật' if state else 'tắt'} {name}.")

def announce_error(reason: str = "không hiểu lệnh") -> None:
    speak(f"Xin lỗi, tôi {reason}.")

Test phần cứng

# test_gpio.py
import time, gpio_controller
gpio_controller.init()
for device in ["light","fan","ac","socket"]:
    gpio_controller.set_device(device, True);  time.sleep(1)
    gpio_controller.set_device(device, False); time.sleep(0.5)
print("States:", gpio_controller.get_states())
gpio_controller.cleanup()
python test_gpio.py