# Basic Motor Torque Control Application

In this application, you will learn how to control the **torque (current)** of a brushed DC motor using the **Torque Mode** of the SMD Red module. You will input a torque value between `-100` and `100`, and observe the motor’s response. This control mode is particularly useful for applications that require **force feedback**, **current-limited motion**, or **haptic interaction**.

**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](https://docs.acrome.net/electronics/gateway-modules/arduino-gateway-module) ([Purchase Here](https://www.robotshop.com/products/acrome-arduino-gateway-shield-module-acrome-smd-products))

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

## **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 Red](/electronics/smd-red.md): Drives the DC motor and manages current control via internal PID loop.
2. [BDC Motor](/electronics/electrical-motors/brushed-dc-motors-bdc.md): Converts electrical energy into mechanical torque.

#### **Project Key Features**

1. Real-time torque input via command line
2. Bidirectional torque control (±100)
3. Live current measurement feedback
4. PID-based torque regulation

## **Step 2: Assemble** <a href="#step-2-assemble" id="step-2-assemble"></a>

#### **Getting Started**

**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) or [Arduino Gateway Module](https://acrome.gitbook.io/acrome-smd-docs/electronics/gateway-modules/arduino-gateway-module).
* Connect the 100 RPM [BDC Motor](https://docs.acrome.net/electronics/electrical-motors/brushed-dc-motors-bdc) with Encoder to the motor ports of the SMD Red.
* Make sure that the SMD is powered and all connections are correct.

#### **Project Wiring Diagram**

<figure><img src="/files/1bc65n9gm1iZlqh9GDn8" alt=""><figcaption></figcaption></figure>

## Step 3: Run & Test <a href="#step-3-run-and-test" id="step-3-run-and-test"></a>

#### Run the Script

You will be prompted to enter a torque value in the range of `-100` to `100`.\
The motor will apply the specified current, and the system will print both the target and actual measured torque.

## Codes

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

```python
from smd.red import *  # Import the SMD Red Python library
from serial.tools.list_ports import comports  # Used to detect available serial (COM) ports
from platform import system  # Used to identify the current operating system
import time  # For time delays

# Function to automatically detect the correct USB port where SMD Red is connected
def USB_Port():
    ports = list(comports())  # Get list of all serial ports
    usb_names = {
        "Windows": ["USB Serial Port"],
        "Linux": ["/dev/ttyUSB"],
        "Darwin": ["/dev/cu."]  # macOS serial devices typically start with /dev/cu.
    }
    os_name = system()
    for port, desc, _ in ports:
        # Return the first matching port based on platform-specific device names
        if any(name in port or name in desc for name in usb_names.get(os_name, [])):
            return port
    return None  # If no matching port is found, return None

# Main function that sets up and runs the torque control loop
def main():
    port = USB_Port()
    if not port:
        print("No port found.")  # Exit if no SMD Red is detected
        return

    master = Master(port)  # Create a Master object to communicate with the SMD Red
    motor_id = 1  # Set the motor ID (default is 1)

    # Attach the SMD Red module and configure it
    master.attach(Red(motor_id))  # Attach the motor
    master.set_shaft_cpr(motor_id, 6533)  # Set encoder resolution (not used in torque mode, but good practice)
    master.set_shaft_rpm(motor_id, 100)  # Set motor's nominal speed (not critical for torque mode)
    
    # Set torque control parameters (PID: P=3.0, I=0.1, D=0.0)
    master.set_control_parameters_torque(motor_id, 3.0, 0.1, 0.0)

    # Enable Torque mode
    master.set_operation_mode(motor_id, OperationMode.Torque)

    # Enable the motor torque output
    master.enable_torque(motor_id, True)

    # Loop to continuously read user input and set torque
    while True:
        try:
            # Read torque input from user
            current = float(input("Enter desired torque current (-100 to 100): "))
            
            # Send torque value to the motor
            master.set_torque(motor_id, current)

            # Read and print actual measured current from the motor
            measured = master.get_torque(motor_id)
            print(f"Set: {current:.2f}, Measured: {measured:.2f}\n")

            time.sleep(0.2)  # Small delay for stability
        except KeyboardInterrupt:
            # On Ctrl+C, safely disable torque and exit the loop
            master.enable_torque(motor_id, False)
            break

# Entry point of the script
if __name__ == "__main__":
    main()
```

{% endcode %}
{% endtab %}

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

```cpp
#include <Acrome-SMD.h>
#define BAUDRATE 115200         // Serial communication speed
#define ID 1                    // ID of the SMD Red module

Red master(ID, Serial, BAUDRATE);  // Create SMD Red object
int currentLimit = 100;            // Max allowed current
bool torqueEnabled = true;         // Motor torque status

void setup() {
  Serial.begin(115200);            // Start serial monitor
  master.begin();                  // Initialize communication with SMD Red
  master.setOperationMode(TorqueControl);  // Set operation mode to Torque Control
  master.torqueEnable(1);         // Enable motor torque
}

void loop() {
  // Read joystick X and Y values from module 1
  int joystickX = master.getJoystickX(1);
  int joystickY = master.getJoystickY(1);

  // Adjust current limit based on joystick direction
  if (joystickX > 50 || joystickY > 50) {
    currentLimit++;
  } else if (joystickX < -50 || joystickY < -50) {
    currentLimit--;
  }

  // Send torque setpoint to motor
  master.setpoint(3, currentLimit - 50);  // Adjust for offset
  int current = master.getTorque();       // Read current draw from motor

  // Debug output
  Serial.print("Motor Current: "); Serial.println(current);
  Serial.print("Current Limit: "); Serial.println(currentLimit);

  // Safety: Disable motor if current exceeds limit
  if (current >= currentLimit) {
    master.torqueEnable(0);  // Disable torque
    torqueEnabled = false;
    Serial.println("Motor disabled due to overcurrent!");
  }

  delay(100);  // Small delay for stability
}
```

{% 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/basic-motor-torque-control-application.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.
