# 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](https://docs.acrome.net/electronics/add-on-modules/joystick-module), two servo motors, two [Servo Modules](https://docs.acrome.net/electronics/add-on-modules/servo-module). 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](https://docs.acrome.net/electronics/add-on-modules/joystick-module). A webcam or a [Ultrasonic Distance Sensor Module](https://docs.acrome.net/electronics/add-on-modules/ultrasonic-distance-sensor-module) can be connected to the Pan-Tilt Control System.

<figure><img src="https://1077748559-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LuxEcL3mxZNc5Aa92N6%2Fuploads%2FhpvlBqraZfE2T7NMyYIF%2F0118-ezgif.com-optimize.gif?alt=media&#x26;token=b5ddd1ec-5f2e-43d6-a143-2c7df7dff99b" 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](https://docs.acrome.net/electronics/add-on-modules/servo-module) ([Purchase Here](https://www.robotshop.com/products/acrome-rc-servo-add-on-module-acrome-smd-products))

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

[Ultrasonic Distance Sensor](https://docs.acrome.net/electronics/add-on-modules/ultrasonic-distance-sensor-module) ([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**](https://docs.acrome.net/electronics/smd-red)

   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](https://docs.acrome.net/electronics/add-on-modules/joystick-module) and control the two servo motors by the [Servo Modules](https://docs.acrome.net/electronics/add-on-modules/servo-module) in 2 different axes.
2. [**Servo Module**](https://docs.acrome.net/electronics/add-on-modules/servo-module)

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

   The [Joystick Module](https://docs.acrome.net/electronics/add-on-modules/joystick-module) allows the user to control the two servo motors, thus, two axes simultaneously.
4. [Ultrasonic Distance Sensor](https://docs.acrome.net/electronics/add-on-modules/ultrasonic-distance-sensor-module)\
   The [Ultrasonic Distance Sensor](https://docs.acrome.net/electronics/add-on-modules/ultrasonic-distance-sensor-module) 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**](https://docs.acrome.net/software/libraries)

   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](https://docs.acrome.net/electronics/add-on-modules/joystick-module) 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](https://docs.acrome.net/electronics/add-on-modules/joystick-module), 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](https://docs.acrome.net/electronics/add-on-modules/joystick-module) and two [Servo Modules](https://docs.acrome.net/electronics/add-on-modules/servo-module) 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](https://docs.acrome.net/electronics/add-on-modules/servo-module).
   * Make sure that the SMD is powered and all connections are correct.

#### Project Wiring Diagram

<figure><img src="https://1077748559-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LuxEcL3mxZNc5Aa92N6%2Fuploads%2FLYrZNv4gnSJwXzIu8PME%2FPan-tilt.png?alt=media&#x26;token=e5715e14-15d6-4d75-9047-e958c7f2a06e" 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 %}
