# Distance Auto Stop

This project showcases a dynamic motor control system utilizing the [ACROME SMD](/electronics/smd-red.md) platform. The project integrates hardware, real-time processing, and dynamic scaling to achieve precision control. The goal is to create a motorized system where the speed decreases as the motor approaches an object and stops completely when it gets very close. This is achieved using distance measurements and velocity interpolation.

**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))

[Arduino Gateway Module](/electronics/gateway-modules/arduino-gateway-module.md) ([Purchase Here](https://www.robotshop.com/products/acrome-arduino-gateway-shield-module-acrome-smd-products))

[BDC Motor](/electronics/electrical-motors/brushed-dc-motors-bdc.md) ([Purchase Here](https://www.robotshop.com/products/acrome-12v-brushed-dc-motor-with-built-in-encoder-100-rpm-speed))

[Ultrasonic Distance Sensor Module](/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. [**ACROME SMD Red Platform**](/electronics/smd-red.md)\
   The [ACROME SMD](/electronics/smd-red.md) platform serves as the control hub, interfacing with the motor and reading sensor data.
2. [**Ultrasonic Distance Sensor**](/electronics/add-on-modules/ultrasonic-distance-sensor-module.md)\
   A distance sensor is used to measure the object's position in real-time.
3. [BDC Motor](/electronics/electrical-motors/brushed-dc-motors-bdc.md)\
   The motor is controlled using velocity commands, allowing for smooth acceleration and deceleration.

### **Key Features**

1. **Distance-Based Motor Control**\
   The motor dynamically adjusts its speed based on proximity.
2. **Smooth Interpolation**\
   The velocity decreases gradually instead of abrupt stops, ensuring smoother operation.
3. **Real-Time Feedback**\
   The system logs current distance and velocity values for monitoring.

## **Step 2: Assemble**

**Getting Started**

1. **Hardware Setup**
   * Connect the [SMD Red ](/electronics/smd-red.md)to the PC or Arduino board using [USB Gateway Module](/electronics/gateway-modules/usb-gateway-module.md) or [Arduino Gateway Module](/electronics/gateway-modules/arduino-gateway-module.md).
   * Connect the [Ultrasonic Distance Sensor ](/electronics/add-on-modules/ultrasonic-distance-sensor-module.md)to the SMD using an RJ-45 cable.
   * Make sure that the SMD is powered and all connections are correct.

#### **Project Wiring Diagram**

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

## Step 3: Run & Test

1. **Run the Script**
   * Run the script on your computer. This will establish communication with the SMD and initiate control of the [Ultrasonic Distance Sensor](/electronics/add-on-modules/ultrasonic-distance-sensor-module.md).

## Codes

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

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


# Serial Communication Settings
baudrate = 115200           # Baud rate for communication
module_id = 0               # ID of the SMD module
distance_sensor_id = 1      # ID of the distance sensor module
motor_id = 0                # ID of the motor module


# Distance Thresholds and Motor Speed Settings
middle_distance = 20        # Medium distance threshold (cm)
near_distance = 5           # Close distance threshold (cm)
max_speed = 100             # Maximum motor speed


def detect_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.
    """
    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()
    print(f"Operating System: {os_name}")

    if ports:
        for port in ports:
            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
        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


# Initialize the USB port and SMD module
SerialPort = detect_usb_port()
if SerialPort is None:
    print("No suitable USB port found.")
    exit(1)

master = Master(SerialPort, baudrate)
master.attach(Red(module_id))


# Motor Configuration
master.set_shaft_cpr(motor_id, 6533)  # Set encoder counts per revolution
master.set_shaft_rpm(motor_id, 100)   # Set maximum RPM
master.enable_torque(motor_id, 1)     # Enable motor torque


# Function for Speed Interpolation
def interpolate_speed(distance):
    """
    Calculates the motor speed based on distance using linear interpolation.

    Args:
        distance (float): The measured distance from the sensor.

    Returns:
        float: The calculated speed.
    """
    if distance < near_distance:
        return 0  # Stop the motor
    elif near_distance <= distance < middle_distance:
        return max(10, max_speed * (distance - near_distance) / (middle_distance - near_distance))  # Smooth acceleration
    else:
        return max_speed  # Full speed


# Main Control Loop
while True:
    distance = master.get_distance(module_id, distance_sensor_id)

    if distance is not None:
        speed = interpolate_speed(distance)
        master.set_duty_cycle(motor_id, speed)

        if speed == 0:
            print("Motor Stopped")
        elif speed == max_speed:
            print("Motor Running at Max Speed")
        else:
            print(f"Motor Running at Speed: {speed}")
```

{% endcode %}
{% endtab %}

{% tab title="Arduino Code" %}
{% code lineNumbers="true" %}

```cpp
#include <Acrome-SMD.h>
#define ID         0 
#define CPR        6533   
#define BAUDRATE   115200 

Red master(ID, Serial, BAUDRATE); 

void setup() {
  master.begin();
  master.torqueEnable(1);       
  Serial.begin(115200); 
}

void loop() {
  int distance = master.getDistance(1);
  Serial.print("Distance: ");
  Serial.println(distance);

  // Define velocity scaling parameters
  int maxVelocity = 1000;  // Maximum velocity 
  int minVelocity = 0;     // Minimum velocity
  int stopDistance = 20;   // Distance at which motor should start slowing down
  int fullStopDistance = 5; // Distance at which motor completely stops

  // Check if motor needs to slow down or stop
  int velocity;
  if (distance > stopDistance) {
    // Full speed if distance is greater than stop threshold
    velocity = maxVelocity;
  } else if (distance > fullStopDistance) {
    // Gradually reduce velocity as distance decreases
    velocity = map(distance, fullStopDistance, stopDistance, 0, maxVelocity);
  } else {
    // Completely stop the motor when very close
    velocity = 0;
  }

  // Set motor to velocity mode and set velocity
  master.setOperationMode(2);
  master.setpoint(2, velocity);

  // Small delay to prevent overwhelming the system
  delay(50);
}
```

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

### **Conclusion**

This project highlights the [ACROME SMD Red](/electronics/smd-red.md) platform's versatility in creating advanced motor control systems. By combining real-time distance sensing with velocity interpolation, it provides a robust solution for a range of applications.


---

# 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/basics/distance-auto-stop.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.
