Joystick Mouse Control

This project is an interactive system that controls the computer's mouse cursor using a Joystick Module connected to the ACROME SMD. The user can adjust the mouse sensitivity dynamically through a graphical interface and perform mouse clicks using the Joystick Module. The system continuously monitors Joystick Module inputs and responds accordingly, providing a seamless user experience for controlling the mouse cursor.

About Tools and Materials:

SMD Red (Purchase Here)

SMD USB Gateway (Purchase Here)

Joystick Module (Purchase Here)

Step 1: Hardware & Software Overview

Key Components:

  1. ACROME SMD The ACROME SMD acts as the communication hub between the Joystick Module and the computer. It collects Joystick Module data, processes user input, and translates it into mouse movements and clicks.

  2. Joystick Module The Joystick Module serves as the main input device. The user can move the Joystick Module to control the mouse pointer’s X and Y coordinates on the screen. Additionally, the Joystick Module button can be used to trigger mouse clicks.

  3. GUI (Tkinter) A graphical user interface (GUI) is used to display real-time Joystick Module values (X and Y axes), sensitivity levels, and the button status. The GUI also allows the user to manually adjust the sensitivity for finer control.

Project Features:

  1. Real-Time Joystick Mouse Control The system continuously reads the X and Y values from the Joystick Module and moves the mouse pointer based on those inputs. The Joystick Module’s button is mapped to mouse clicks, allowing users to interact with on-screen elements.

  2. Dynamic Sensitivity Adjustment The system features dynamic sensitivity control, which adjusts the mouse movement speed based on the Joystick Module’s input magnitude. Users can also manually set the base sensitivity via the GUI for greater precision.

  3. Graphical Interface for Feedback The GUI provides real-time feedback to the user, displaying the current X and Y values of the Joystick Module, the sensitivity, and whether the Joystick Module button is pressed or released. This ensures transparency in how the Joystick Module movements are translated into mouse actions.

  4. Manual Sensitivity Input The user can adjust the base sensitivity through an input field in the GUI. Once entered, the new sensitivity is applied, and the system updates the sensitivity label accordingly.

  5. Multithreading for Real-Time Control To ensure the mouse control happens smoothly without interrupting the GUI, the system uses a separate thread for handling the joystick inputs and mouse control. This ensures that both the GUI and joystick functionalities run in parallel without delays.

Step 2: Assemble

Workflow:

  1. Joystick Module Data Monitoring The system continuously reads the Joystick Module's X, Y, and button values. These inputs control the mouse pointer’s movements and clicks.

  2. Mouse Movement Control Based on the Joystick Module’s X and Y axis values, the system calculates the new mouse pointer position and moves the cursor accordingly. The movement speed is influenced by both the base sensitivity and dynamic multiplier, which adjusts based on the Joystick Module's movement magnitude.

  3. Button Click Simulation If the Joystick Module’s button is pressed, the system simulates a mouse click. The button press also temporarily increases the base sensitivity for quicker movements.

  4. GUI Updates The GUI continuously updates with the latest Joystick Module values, sensitivity, and button status, providing visual feedback to the user.

Getting Started

  1. Connect the SMD: Connect the ACROME SMD to your PC using a USB Gateway Module or to an Arduino board using the Arduino Gateway Module.

  2. Set Up the Joystick Module: Connect the Joystick Module to the SMD using an RJ-45 cable.

  3. Power Connections: Ensure that the SMD is powered and that all connections are securely made.

Project Wiring Diagram

Step 3: Run & Test

  1. Run the Application:

    • Execute the provided Python script to start the Joystick Mouse Control application.

    • Once the application is running, move the Joystick Module to control the mouse cursor on your screen. Experiment with different Joystick Module movements to understand how they translate to mouse actions.

  2. Adjust Sensitivity: Use the GUI to adjust the sensitivity settings for finer control as needed.

from smd.red import *
import time
import pyautogui
import tkinter as tk
from threading import Thread
from serial.tools.list_ports import comports
from platform import system

pyautogui.FAILSAFE = False

baudrate = 115200          # Baud rate of communication
ID = 0                     # ID of the SMD
joystick_id = 5            # ID of the joystick module
button_id = 5              # ID of the button module


def USB_Port():
    """
    Scans and identifies a compatible USB port for the current operating system.

    Returns:
        str: The detected USB port or None if no suitable port is found.
    """
    # Get a list of available ports
    ports = list(comports())

    # Known USB port names for different operating systems
    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",
        ]
    }

    # Detect the operating system
    os_name = system()
    print(f"Operating System: {os_name}")

    if ports:
        for port in ports:
            # Check if the port matches any known USB names
            if any(name in port.device or name in port.description for name in usb_names.get(os_name, [])):
                print(f"USB device detected on port: {port.device}")
                return port.device  # Return the first matching port
        # If no suitable port is found, print the list of available ports
        print("No suitable USB device found. Available ports:")
        for port in ports:
            print(f"Port: {port.device}, Description: {port.description}, HWID: {port.hwid}")
    else:
        print("No ports detected!")
    return None


# Find and initialize the USB port
SerialPort = USB_Port()
if not SerialPort:
    raise Exception("No compatible USB port found. Please check your connection.")

# Initialize the SMD module
master = Master(SerialPort, baudrate)
master.attach(Red(ID))
print("Connected Modules:", master.scan_modules(ID))


# Sensitivity settings
base_sensitivity = 0.5  # Default sensitivity
dynamic_multiplier = 1.0  # Multiplier for dynamic sensitivity


# GUI setup
window = tk.Tk()
window.title("Joystick Mouse Control")
window.geometry("300x300")

x_label = tk.Label(window, text="X Value: 0", font=("Helvetica", 14))
x_label.pack(pady=10)

y_label = tk.Label(window, text="Y Value: 0", font=("Helvetica", 14))
y_label.pack(pady=10)

sensitivity_label = tk.Label(window, text="Sensitivity: 0.5", font=("Helvetica", 14))
sensitivity_label.pack(pady=10)

button_status_label = tk.Label(window, text="Button Status: Released", font=("Helvetica", 14))
button_status_label.pack(pady=10)

sensitivity_entry = tk.Entry(window)
sensitivity_entry.pack(pady=10)
sensitivity_entry.insert(0, str(base_sensitivity))


def update_gui(x_val, y_val, sensitivity, button_status):
    """
    Updates GUI elements with joystick values, sensitivity, and button status.
    """
    x_label.config(text=f"X Value: {x_val:.2f}")
    y_label.config(text=f"Y Value: {y_val:.2f}")
    sensitivity_label.config(text=f"Sensitivity: {sensitivity:.2f}")
    button_status_label.config(text=f"Button Status: {button_status}")


def update_sensitivity():
    """
    Updates the base sensitivity for joystick control based on user input.
    """
    global base_sensitivity
    try:
        base_sensitivity = float(sensitivity_entry.get())
        sensitivity_label.config(text=f"Sensitivity: {base_sensitivity:.2f}")
    except ValueError:
        sensitivity_label.config(text="Invalid sensitivity value")


apply_button = tk.Button(window, text="Apply Sensitivity", command=update_sensitivity)
apply_button.pack(pady=10)


def joystick_control():
    """
    Handles joystick input for mouse control.
    """
    global base_sensitivity, dynamic_multiplier

    while True:
        joystick = master.get_joystick(ID, joystick_id)
        if joystick is None:
            print("Joystick not connected!")
            continue

        x_val, y_val = joystick[0], joystick[1]
        button_status = "Pressed" if master.get_button(ID, button_id) == 1 else "Released"

        # Update dynamic multiplier
        dynamic_multiplier = max(1.0, min(5.0, (abs(x_val) + abs(y_val)) / 50))

        # Adjust sensitivity
        x_val *= base_sensitivity * dynamic_multiplier
        y_val *= base_sensitivity * dynamic_multiplier
        y_val *= -1  # Invert Y-axis for proper mouse movement

        # Update mouse position
        if abs(x_val) > 5 or abs(y_val) > 5:
            pyautogui.moveRel(x_val, y_val)

        # Handle button click
        if joystick[2] == 1:
            pyautogui.click()

        # Update GUI
        update_gui(joystick[0], joystick[1], base_sensitivity, button_status)

        time.sleep(0.01)


# Start joystick control in a separate thread
joystick_thread = Thread(target=joystick_control)
joystick_thread.daemon = True
joystick_thread.start()

# Run the GUI loop
window.mainloop()

Conclusion: This project demonstrates how the ACROME SMD can be used to create an interactive joystick-controlled system for managing mouse movements. By integrating real-time Joystick Module input with dynamic sensitivity control and a graphical interface for user feedback, the system provides an intuitive and customizable solution for precise cursor control.

Last updated