# Pan-Tilt with Joystick Module

The Pan-Tilt Control System is a project that is widely used in many areas. It contains the [Joystick Module](/electronics/add-on-modules/joystick-module.md), two servo motors, two [Servo Modules](/electronics/add-on-modules/servo-module.md). The two servo motors provide a 2 DOF movement to the mechanism, one is horizontal (pan) and the other one is vertical (tilt) DOFs. These movement axes can be controlled through the [Joystick Module](/electronics/add-on-modules/joystick-module.md). A webcam or a [Ultrasonic Distance Sensor Module](/electronics/add-on-modules/ultrasonic-distance-sensor-module.md) can be connected to the Pan-Tilt Control System.

<figure><img src="/files/EvBqO2zuEdgW6O2e0aeR" alt=""><figcaption></figcaption></figure>

**About Tools and Materials:**

[SMD Red](https://docs.acrome.net/electronics/smd-red) ([Purchase Here](https://www.robotshop.com/products/acrome-smd-red-smart-brushed-motor-driver-with-speed-position-and-current-control-modes))

[SMD USB Gateway](https://docs.acrome.net/electronics/gateway-modules/usb-gateway-module) ([Purchase Here](https://www.robotshop.com/products/acrome-usb-gateway-module-acrome-smd-products))

2x [Servo Module](/electronics/add-on-modules/servo-module.md) ([Purchase Here](https://www.robotshop.com/products/acrome-rc-servo-add-on-module-acrome-smd-products))

[Joystick Module](/electronics/add-on-modules/joystick-module.md) ([Purchase Here](https://www.robotshop.com/products/acrome-joystick-2-axis-add-on-module-acrome-smd-products))

[Ultrasonic Distance Sensor](/electronics/add-on-modules/ultrasonic-distance-sensor-module.md) ([Purchase Here](https://www.robotshop.com/products/acrome-ultrasonic-distance-sensor-add-on-module-acrome-smd-products))

## **Step 1: Hardware & Software Overview** <a href="#step-1-hardware-and-software-overview" id="step-1-hardware-and-software-overview"></a>

**Project Key Components**

1. [**SMD**](/electronics/smd-red.md)

   The SMD acts as a bridge between the script and the modules. It is responsible for interpreting the commands sent by the script and translating them into actions that read input from the [Joystick Module](/electronics/add-on-modules/joystick-module.md) and control the two servo motors by the [Servo Modules](/electronics/add-on-modules/servo-module.md) in 2 different axes.
2. [**Servo Module**](/electronics/add-on-modules/servo-module.md)

   The Servo Module drives the servo motor that is connected to it. It can be controlled through the [SMD libraries](/software/libraries.md).
3. [**Joystick Module**](/electronics/add-on-modules/joystick-module.md)

   The [Joystick Module](/electronics/add-on-modules/joystick-module.md) allows the user to control the two servo motors, thus, two axes simultaneously.
4. [Ultrasonic Distance Sensor](/electronics/add-on-modules/ultrasonic-distance-sensor-module.md)\
   The [Ultrasonic Distance Sensor](/electronics/add-on-modules/ultrasonic-distance-sensor-module.md) enhances the Pan-Tilt System by enabling real-time object detection and tracking. Mounted on the tilt axis, it measures distances and can trigger alerts for nearby obstacles.
5. [**SMD Libraries**](/software/libraries.md)

   The SMD library is at the heart of the application. It communicates with the SMD using a specific communication protocol, sending commands to read the [Joystick Module](/electronics/add-on-modules/joystick-module.md) and send the servo motor control inputs to the Servo Modules.

**Project Key Features**

* **Flexible Position Control**\
  The Pan-Tilt Control System allows the user to control the mounted object in a flexible vay due to two servo motors and the precise motor driving capability of the SMD.
* **Intuitive Manual Control**\
  Through the [Joystick Module](/electronics/add-on-modules/joystick-module.md), the users can intuitively control the 2 DOF Pan-Tilt Control System.

## **Step 2: Assemble**

**Getting Started**

1. **Hardware Setup**
   * Connect the SMD to the PC or Arduino board using [USB Gateway Module](https://acrome.gitbook.io/acrome-smd-docs/electronics/gateway-modules/usb-gateway-module) .
   * Connect the [Joystick Module](/electronics/add-on-modules/joystick-module.md) and two [Servo Modules](/electronics/add-on-modules/servo-module.md) to the SMD using an RJ-45 cable.
   * Attach the servo motors to the designated axes for pan (horizontal) and tilt (vertical) movements.
   * Connect the each servo motor to the [Servo Modules](/electronics/add-on-modules/servo-module.md).
   * Make sure that the SMD is powered and all connections are correct.

#### Project Wiring Diagram

<figure><img src="/files/MM6CtW4EWBtqbMz86rlb" alt=""><figcaption></figcaption></figure>

## Step 3: Run & Test

1. **Run the Script**
   * Execute the script, initiating the Pan-Tilt Control System application.
   * Move the joystick to see how the system works when different axes of joystick are used.

## **Codes**

{% tabs %}
{% tab title="Python Code" %}
{% code lineNumbers="true" %}

```python
from smd.red import *
import numpy as np
from serial.tools.list_ports import comports
from platform import system

baudrate = 115200          # Baud rate of communication
ID = 0                     # ID of the SMD
joystick_id = 5            # ID of the joystick module
servo_pan_id = 5           # ID of the pan servo
servo_tilt_id = 5          # ID of the tilt servo


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"],  # Names specific to Windows
        "Linux": ["/dev/ttyUSB"],        # Names specific to Linux
        "Darwin": [                      # Names specific to macOS
            "/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


try:
    # 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)       # Defines the USB gateway module
    master.attach(Red(ID))                      # Gives access to the SMD of specified ID
    print("Driver Info:", master.get_driver_info(ID))  # Print driver information
    print("Connected Modules:", master.scan_modules(ID))  # Scan and display connected modules

    # Main loop for joystick control
    while True:
        joystick_position = master.get_joystick(ID, joystick_id)  # Read joystick position
        if joystick_position is None:
            print("SMD connection issue:", master.get_driver_info(ID))
        else:
            # Adjust joystick X-axis value
            joystick_position[0] += 20
            if joystick_position[0] < 0:
                joystick_position[0] = np.interp(joystick_position[0], (-80, 0), (-100, 0))
            else:
                joystick_position[0] = np.interp(joystick_position[0], (0, 120), (0, 100))

            # Print joystick positions for debugging
            print("Joystick Y:", joystick_position[1])
            print("Joystick X:", joystick_position[0])

            # Set servo angles based on joystick position
            pan_angle = int(np.interp(joystick_position[0], (-100, 100), (0, 180)))
            tilt_angle = int(np.interp(joystick_position[1], (-100, 100), (0, 180)))
            master.set_servo(ID, servo_pan_id, pan_angle)  # Pan axis servo control
            master.set_servo(ID, servo_tilt_id, tilt_angle)  # Tilt axis servo control

except Exception as e:
    print(f"Error: {e}")
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.acrome.net/smd-applications/interactive/pan-tilt-with-joystick-module.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
