Negar Rafieedolatabadi
Published

Voice-Activated Smart Air Quality Monitor Using SEN55

Create a smart air quality monitor perfect for spaces like a baby room, using a Raspberry Pi, SEN55 sensor, microphone, and smart plug.

BeginnerProtip3 hours254
Voice-Activated Smart Air Quality Monitor Using SEN55

Things used in this project

Hardware components

Sensirion SEN55
×1
Raspberry Pi Zero
Raspberry Pi Zero
×1
Sonos speakers
Sonos speakers
×1
mini usb microphone
×1
Jumper wires (generic)
Jumper wires (generic)
×1
smart plug
×1

Software apps and online services

Tuya Developer Platform

Story

Read more

Schematics

Schematic Design

Video of performance

Wire connections

Code

Python code for SEN55

RDoc
The code for the smart air quality monitor continuously reads data from the SEN55 sensor to monitor temperature, humidity, PM levels, and VOC concentrations. It checks these values against predefined thresholds and, if any metrics exceed safe limits, it activates a smart plug to turn on a fan or humidifier using voice commands. Additionally, it listens for specific voice commands to allow manual control of the devices, ensuring a comfortable and healthy environment in the baby room.
import time
import os
import subprocess  # Import subprocess
from gtts import gTTS
import speech_recognition as sr  # For recognizing speech
from sensirion_i2c_driver import I2cConnection, LinuxI2cTransceiver
from sensirion_i2c_sen5x import Sen5xI2cDevice
import tinytuya  # Import TinyTuya for smart plug control

# Device configuration for the smart plug
DEVICE_ID = 'eb386bf127a9f60a6e4mi5'  # From Tuya IoT platform
DEVICE_IP = '192.168.12.203'  # IP address of your plug
DEVICE_LOCAL_KEY = 'bE9>0u^&iTiTW:B?'  # Local key from the Tuya IoT platform

# Set up the plug object
plug = tinytuya.OutletDevice(DEVICE_ID, DEVICE_IP, DEVICE_LOCAL_KEY)
plug.set_version(3.4)  # Some devices use 3.3 protocol, adjust if necessary

def speak_message(message):
    """Function to convert text to speech using gTTS and play it."""
    tts = gTTS(text=message, lang='en')
    tts.save("output.mp3")
    
    # Use subprocess to call mpg321 and wait until it finishes
    subprocess.run(["mpg321", "output.mp3"])

def listen_for_yes_no():
    """Function to listen for 'yes' or 'no' using microphone."""
    recognizer = sr.Recognizer()
    mic = sr.Microphone()

    with mic as source:
        print("Listening for a response...")
        recognizer.adjust_for_ambient_noise(source)
        audio = recognizer.listen(source)

    try:
        # Recognize speech using Google Speech Recognition
        response = recognizer.recognize_google(audio).lower()
        print(f"You said: {response}")
        if 'yes' in response:
            return 'yes'
        elif 'no' in response:
            return 'no'
        else:
            return None
    except sr.UnknownValueError:
        print("Sorry, I couldn't understand the audio.")
        return None
    except sr.RequestError as e:
        print(f"Could not request results; {e}")
        return None

def turn_on_plug():
    """Function to turn on the smart plug."""
    print("Turning on the plug...")
    plug.turn_on()
    print("Plug is now ON.")

def turn_off_plug():
    """Function to turn off the smart plug."""
    print("Turning off the plug...")
    plug.turn_off()
    print("Plug is now OFF.")

try:
    with LinuxI2cTransceiver('/dev/i2c-1') as i2c_transceiver:
        device = Sen5xI2cDevice(I2cConnection(i2c_transceiver))

        # Print device information
        print("Version: {}".format(device.get_version()))
        print("Product Name: {}".format(device.get_product_name()))
        print("Serial Number: {}".format(device.get_serial_number()))

        # Reset and start measurement
        device.device_reset()
        device.start_measurement()
        print("Measurement started. Press Ctrl+C to stop.")

        last_warning_time = 0  # Initialize the warning time
        while True:
            print("Waiting for new data...")
            while not device.read_data_ready():
                time.sleep(0.1)

            values = device.read_measured_values()
            ambient_humidity = values.ambient_humidity.percent_rh
            pm_2p5 = values.mass_concentration_2p5.physical if hasattr(values.mass_concentration_2p5, 'physical') else None
            voc_index = values.voc_index.physical if hasattr(values.voc_index, 'physical') else None

            print(f"Ambient Humidity: {ambient_humidity:.2f}%RH")
            print(f"PM2.5: {pm_2p5:.2f} µg/m³" if pm_2p5 is not None else "PM2.5 data not available")
            print(f"VOC Index: {voc_index:.2f}" if voc_index is not None else "VOC data not available")

            # Check if any thresholds are exceeded and announce warnings
            current_time = time.time()  # Get the current time
            if ambient_humidity > 70 and (current_time - last_warning_time > 60):
                message = f"Warning! Humidity is above 70 percent. Current humidity is {ambient_humidity:.2f}%RH."
                print(message)
                speak_message(message)
                last_warning_time = current_time  # Update the last warning time
                time.sleep(2)  # Delay before asking about the fan

                speak_message("Would you like to turn on the fan? Please say yes or no.")
                time.sleep(3)  # Wait for 3 seconds before listening
                response = listen_for_yes_no()

                if response == 'yes':
                    speak_message("Okay, turning on the fan.")
                    turn_on_plug()  # Turn on the plug
                elif response == 'no':
                    speak_message("Okay, the fan will remain off.")
                else:
                    speak_message("I didn't catch that. Please try again.")

            if pm_2p5 is not None and pm_2p5 > 35 and (current_time - last_warning_time > 60):
                message = f"Warning! PM2.5 levels are high. Current level is {pm_2p5:.2f} micrograms per cubic meter."
                print(message)
                speak_message(message)
                last_warning_time = current_time
                time.sleep(0)

                speak_message("Would you like to turn on the fan? Please say yes or no.")
                time.sleep(1)
                response = listen_for_yes_no()

                if response == 'yes':
                    speak_message("Okay, turning on the fan.")
                    turn_on_plug()  # Turn on the plug
                elif response == 'no':
                    speak_message("Okay, the fan will remain off.")
                else:
                    speak_message("I didn't catch that. Please try again.")

            if voc_index is not None and voc_index > 200 and (current_time - last_warning_time > 60):
                message = f"Warning! VOC levels are high. Current VOC index is {voc_index:.2f}."
                print(message)
                speak_message(message)
                last_warning_time = current_time
                time.sleep(2)

                speak_message("Would you like to turn on the fan? Please say yes or no.")
                time.sleep(3)
                response = listen_for_yes_no()

                if response == 'yes':
                    speak_message("Okay, turning on the fan.")
                    turn_on_plug()  # Turn on the plug
                elif response == 'no':
                    speak_message("Okay, the fan will remain off.")
                else:
                    speak_message("I didn't catch that. Please try again.")

            # Sleep before checking values again
            time.sleep(1)

except KeyboardInterrupt:
    device.stop_measurement()
    print("Measurement stopped.")
except Exception as e:
    print(f"An error occurred: {e}")

Credits

Negar Rafieedolatabadi
3 projects • 4 followers

Comments