Smart Light Control

This project focuses on creating an interactive lighting system using the ACROME SMD platform, incorporating an Ambient Light Sensor, an RGB LED Module, and a Button Module. The system allows for automatic lighting control based on ambient light conditions and provides user interactivity to change the LED color. Additionally, the Button Module allows the user to cycle through colors, and when held down, it will quickly transition between colors. The LED will retain the last selected color after the button is released.

About Tools and Materials:

SMD Red (Robot Shop)

SMD USB Gateway (Robot Shop)

RGB LED Module (Robot Shop)

Button Module (Robot Shop)

Ambient Light Sensor Module (Robot Shop)

Step 1: Hardware & Software Overview

Key Components:

  1. SMD The SMD serves as the central communication hub between the different modules. It manages the interaction between the Ambient Light Sensor, RGB LED Module, and Button Module, executing the logic as defined in the script.

  2. RGB LED Module The RGB LED Module emits light in different colors by mixing red, green, and blue channels. This allows users to create a variety of lighting effects, controlled via the Button Module.

  3. Button Module The Button Module serves as a physical interface for user input. Users can press the button to cycle through different colors for the RGB LED Module, and if the button is held down, the system will rapidly cycle through colors, allowing for faster color selection.

  4. Ambient Light Sensor Module The Ambient Light Sensor detects the intensity of the surrounding light and allows the system to decide when to automatically turn on or off the RGB LED Module, depending on the environment’s lighting conditions.

Project Key Features:

  1. Automatic Light Sensing The Ambient Light Sensor Module continuously monitors the environmental light levels. When the light intensity falls below a predefined threshold, the system automatically activates the RGB LED Module. This ensures that the light is only turned on when needed, enhancing energy efficiency and creating an adaptive lighting environment.

  2. Manual Color Control The user can interact with the Button Module to manually change the color of the RGB LED Module. Each button press cycles through a preset list of colors (e.g., red, green, blue, yellow, magenta, cyan). Additionally, holding the button down accelerates the color transitions, allowing users to quickly move between colors.

  3. Energy-Efficient Operation The Ambient Light Sensor Module makes the system more energy-efficient by turning the light off when ambient light levels are sufficient. This feature ensures that the RGB LED Module operates only in low-light conditions, minimizing unnecessary energy usage.

  4. Seamless Module Communication The SMD ensures seamless communication between all components. It reads the ambient light data from the Ambient Light Sensor, controls the color output of the RGB LED, and processes user input from the Button Module. This integration allows the project to react dynamically to both environmental changes and user commands.

Step 2: Assemble

Getting Started

  1. Hardware Setup

Project Wiring Diagram

Step 3: Run & Test

  • Light Monitoring: The system constantly reads ambient light data using the Ambient Light Sensor.

  • Automatic Light Control: If the environment is too dark, the RGB LED Module is automatically turned on, and if the environment is bright, the RGB LED Module turns off.

  • User Interaction: The Button Module allows the user to cycle through colors manually. A single press changes the color, and holding the button down rapidly switches between the colors.

  • Color Retention: When the button is released, the LED remains on the last selected color until further interaction.

Project Codes

from smd.red import *
import time
import tkinter as tk
from tkinter import messagebox  # Uyarı mesajları için
from threading import Thread
import json  # To handle saving and loading from JSON
import os  # To check if the JSON file exists

from serial.tools.list_ports import comports
from platform import system

def USB_Port():
	ports = list(comports())
	usb_names = {
		"Windows": ["USB Serial Port"],
		"Linux": ["/dev/ttyUSB"],
		"Darwin": [
			"/dev/tty.usbserial",
			"/dev/tty.usbmodem",
			"/dev/tty.SLAB_USBtoUART",
			"/dev/tty.wchusbserial",
			"/dev/cu.usbserial",
            		"/dev/cu.usbmodem",
			"/dev/cu.SLAB_USBtoUART",
			"/dev/cu.wchusbserial",
		]
	}
	
	os_name = system()
	if ports:
		for port, desc, hwid in sorted(ports):
			if any(name in port or name in desc for name in usb_names.get(os_name, [])):
				return port
		print("Current ports:")
		for port, desc, hwid in ports:
			print(f"Port: {port}, Description: {desc}, Hardware ID: {hwid}")
	else:
		print("No port found")
	return None
	
port = USB_Port()
m = Master(port)
m.attach(Red(0))

def load_colors_from_json():
    """
    Loads the list of colors from a JSON file named "rgbsetting.json". 
    If the file does not exist or the "colors" key is not present in the JSON data, an empty list is returned.
    
    Returns:
        list: A list of RGB color tuples, or an empty list if the JSON file does not exist or does not contain the "colors" key.
    """
    if os.path.exists("rgbsetting.json"):
        with open("rgbsetting.json", "r") as f:
            data = json.load(f)
            return data.get("colors", [])
    return []

# Predefined default colors in RGB format
default_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255)]

# Load colors from JSON file if available, otherwise use default colors
colors = load_colors_from_json() or default_colors
color_index = 0  # Index for the order of colors

print(m.scan_modules(0))  # Scans the Red SMD module connected to the COM6 serial port and prints the result.

# Create a Tkinter window
window = tk.Tk()
window.title("LED Color Controller")
window.geometry("400x300")


def validate_rgb_value(value):
    """
    Validates an RGB value to ensure it is an integer between 0 and 255 (inclusive).
    
    Args:
        value (str): The RGB value to validate as a string.
    
    Returns:
        bool: True if the value is a valid RGB value, False otherwise.
    """
    try:
        value = int(value)
        if 0 <= value <= 255:
            return True
        else:
            return False
    except ValueError:
        return False
    
def save_color_to_json():
    """
    Saves the current list of colors to a JSON file named "rgbsetting.json".
    
    This function is called when the "Save color to file" checkbox is checked after adding a new color. 
    It creates a dictionary with the "colors" key and assigns the current `colors` list as its value. 
    The dictionary is then written to the "rgbsetting.json" file using the `json.dump()` function.
    
    Args:
        None
    
    Returns:
        None
    """
    data = {"colors": colors}
    with open("rgbsetting.json", "w") as f:
        json.dump(data, f, indent=4)
    print(f"Colors saved to rgbsetting.json")


def add_color():
    """
    Adds a new color to the list of colors based on the RGB values entered in the GUI.
    
    This function is called when the "Add Color" button is clicked in the GUI. 
    It retrieves the RGB values from the corresponding text fields, validates them, 
    and adds the new color to the `colors` list. If the "Save color to file" 
    checkbox is checked, it also saves the updated list of colors to a JSON file.
    
    Args:
        None
    
    Returns:
        None
    """
    r = r_entry.get()
    g = g_entry.get()
    b = b_entry.get()
    
    if validate_rgb_value(r) and validate_rgb_value(g) and validate_rgb_value(b):
        r, g, b = int(r), int(g), int(b)
        colors.append((r, g, b))
        print(f"New color added: R={r}, G={g}, B={b}")
        update_gui("On", "Added", (r, g, b))

        if save_var.get():
            save_color_to_json()
    else:
        messagebox.showerror("Invalid Input", "RGB values must be integers between 0 and 255.")

# Create labels to display light status and button state
light_label = tk.Label(window, text="Light Status: ", font=("Helvetica", 14))
light_label.pack(pady=10)

button_label = tk.Label(window, text="Button State: ", font=("Helvetica", 14))
button_label.pack(pady=10)

color_label = tk.Label(window, text="Current Color: ", font=("Helvetica", 14))
color_label.pack(pady=10)

# RGB input fields and button to add new color
r_label = tk.Label(window, text="R:", font=("Helvetica", 12))
r_label.pack(pady=5, side=tk.LEFT, padx=(10, 0))
r_entry = tk.Entry(window, width=5)
r_entry.pack(pady=5, side=tk.LEFT)

g_label = tk.Label(window, text="G:", font=("Helvetica", 12))
g_label.pack(pady=5, side=tk.LEFT, padx=(10, 0))
g_entry = tk.Entry(window, width=5)
g_entry.pack(pady=5, side=tk.LEFT)

b_label = tk.Label(window, text="B:", font=("Helvetica", 12))
b_label.pack(pady=5, side=tk.LEFT, padx=(10, 0))
b_entry = tk.Entry(window, width=5)
b_entry.pack(pady=5, side=tk.LEFT)

# Checkbox for saving the color to JSON
save_var = tk.BooleanVar()
save_checkbox = tk.Checkbutton(window, text="Save color to file", variable=save_var)
save_checkbox.pack(pady=5)

# Button to trigger adding the new color
add_button = tk.Button(window, text="Add Color", command=add_color)
add_button.pack(pady=10)

def update_gui(light_status, button_status, current_color):
    """
    Updates the GUI to reflect the current light status, button state, and LED color.
    
    This function is responsible for updating the labels and background color of the GUI to match the current state of the RGB LED light. 
    It is called whenever the light status, button state, or LED color changes.
    
    Args:
        light_status (str): The current status of the light, either "On" or "Off".
        button_status (str): The current state of the button, either "Pressed" or "Released".
        current_color (tuple): A tuple containing the current RGB values of the LED light.
    """
    light_label.config(text=f"Light Status: {light_status}")
    button_label.config(text=f"Button State: {button_status}")
    color_label.config(text=f"Current Color: R={current_color[0]}, G={current_color[1]}, B={current_color[2]}")
    window.configure(bg=f'#{current_color[0]:02x}{current_color[1]:02x}{current_color[2]:02x}')

def change_color(index):
    """
    Changes the color of the RGB LED light.
    
    This function is responsible for turning off the LED, then turning on the next color in the `colors` list. It also updates the GUI to reflect the new color.
    
    Args:
        index (int): The index of the color to change to in the `colors` list.
    """
    m.set_rgb(0, 1, 0, 0, 0)
    time.sleep(0.1)
    
    r, g, b = colors[index % len(colors)]
    m.set_rgb(0, 1, r, g, b)
    
    update_gui("On", "Pressed", (r, g, b))

button_held = False
light_status ='Off'
def control_loop():
    """
    The `control_loop()` function is the main control loop for the RGB LED light. It performs the following tasks:
    
    1. Checks the ambient light level and turns the LED on or off accordingly.
    2. Monitors the button state and changes the LED color when the button is pressed.
    3. Updates the GUI to reflect the current light status, button state, and LED color.
    4. Ensures the LED stays on the last selected color when the button is released.
    5. Provides a short delay to control the loop rate.
    
    This function runs in a separate thread to allow the Tkinter main loop to run concurrently.
    """
    global color_index, button_held,light_status
    while True:
        light = m.get_light(0, 1)
        if light is not None:
            light_status = "Off" if light >= 100 else "On"
        if m.get_button(0, 1) == 1:
                if not button_held:
                    button_held = True
                
                change_color(color_index+1)
                color_index += 1 
                time.sleep(0.5)
        else:
                if button_held:
                    button_held = False
                    
        if light is not None:
            if light<100:               
                r, g, b = colors[color_index % len(colors)]
                m.set_rgb(0, 1, r, g, b)
                update_gui(light_status, "Released", (r, g, b))
        else:
            m.set_rgb(0, 1, 0, 0, 0)
            update_gui("Off", "N/A", (0, 0, 0))
        update_gui(light_status, "Pressed" if button_held else "Released", ((r, g, b) if light < 100 else (0, 0, 0)) if light is not None else((0, 0, 0)))
        
        time.sleep(0.01)


control_thread = Thread(target=control_loop)
control_thread.daemon = True
control_thread.start()

window.mainloop()

Conclusion:

This project exemplifies how the ACROME SMD platform can integrate with various modules to create a smart lighting solution that is both interactive and energy-efficient. By using the Ambient Light Sensor, RGB LED, and Button Module, the system combines automatic control with manual user inputs, providing a flexible and customizable lighting experience.

Last updated