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 (Robot Shop)

SMD USB Gateway (Robot Shop)

Joystick Module (Robot Shop)

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
pyautogui.FAILSAFE = False
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))

print(m.scan_modules(0))

# Initialize base sensitivity and dynamic sensitivity multiplier
base_sensitivity = 0.5  
dynamic_multiplier = 1.0  
dynamic_sensitivity_active = False  

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 the GUI elements with the latest joystick values, sensitivity, and button status.
    
    This function is used to update the various labels in the Tkinter window with the current
    joystick X and Y values, the current sensitivity, and the current button status (pressed or
    released). It is called from the `joystick_control()` function to provide real-time feedback
    to the user about the joystick mouse control.
    
    Args:
        x_val (float): The current X-axis value of the joystick.
        y_val (float): The current Y-axis value of the joystick.
        sensitivity (float): The current sensitivity value being used for the joystick mouse control.
        button_status (str): The current status of the joystick button (either "Pressed" or "Released").
    """
    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 the joystick mouse control functionality.
    
    This function is called when the user interacts with the "Apply Sensitivity" button in the GUI.
    It retrieves the sensitivity value entered in the text field, converts it to a float, and updates
    the `base_sensitivity` global variable. The sensitivity label in the GUI is also updated to
    reflect the new sensitivity value.
    
    If the value entered in the text field is not a valid float, an error message is displayed in
    the sensitivity label.
    """
    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 the joystick control functionality for the mouse cursor.
    
    This function continuously reads the joystick input, updates the mouse cursor position, 
    and handles button clicks based on the joystick state. It also dynamically 
    adjusts the mouse sensitivity based on the joystick movement.
    """
    global base_sensitivity, dynamic_multiplier
    
    while True:
        joystick = m.get_joystick(0, 1)
        x_val = joystick[0]
        y_val = joystick[1]
        x_val_i,y_val_i=x_val,y_val
        if m.get_button(0, 1) == 1:
            base_sensitivity += 0.1
            time.sleep(0.2)
            button_status = "Pressed"
        else:
            button_status = "Released"
        dynamic_multiplier = max(1.0, min(5.0, (abs(x_val) + abs(y_val)) / 50))
        x_val *= base_sensitivity * dynamic_multiplier
        y_val *= base_sensitivity * dynamic_multiplier
        y_val *= -1
        if abs(x_val) > 5 or abs(y_val) > 5:
            pyautogui.moveRel(x_val, y_val)

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

        update_gui(x_val_i, y_val_i, base_sensitivity, button_status)

        time.sleep(0.01)

joystick_thread = Thread(target=joystick_control)
joystick_thread.daemon = True  
joystick_thread.start()

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