# 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](https://docs.acrome.net/electronics/smd-red): Drives the DC motor and manages current control via internal PID loop.
2. [BDC Motor](https://docs.acrome.net/electronics/electrical-motors/brushed-dc-motors-bdc): 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="https://1077748559-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LuxEcL3mxZNc5Aa92N6%2Fuploads%2F3fSkR64pSgDlFZHLQs28%2FBasic%20Motor%20Control%20Application%20Using%20PWM%20Input.png?alt=media&#x26;token=4a48a90d-2dbc-4b6a-bd52-c073e293a97d" 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 %}
