# Basic Motor Speed Control Application

This program demonstrates a basic motor control application that adjusts the motor's speed based on user input. It communicates with the motor controller via USB and sets the motor speed (velocity) according to the user's specified value. This allows for simple motor speed control, where the user can input a desired speed, and the motor will rotate accordingly.

**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**](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 [Button Module](https://docs.acrome.net/electronics/add-on-modules/button-module) and actuate the BDC motor, the [RGB LED Module](https://docs.acrome.net/electronics/add-on-modules/rgb-led-module) and the [Buzzer Module](https://docs.acrome.net/electronics/add-on-modules/buzzer-module).
2. [BDC Motor](https://docs.acrome.net/electronics/electrical-motors/brushed-dc-motors-bdc) The motor is controlled using velocity commands, allowing for smooth acceleration and deceleration.

**Project Key Features:**

1. **USB Port Detection**:
   1. The program starts by detecting the available USB serial port for communication with the motor. It uses the `serial` module to find connected serial devices.
   2. The program supports multiple platforms (Windows, Linux, and macOS) and automatically identifies the correct port based on the operating system.
2. **Motor Control with SMD Red**:
   1. The motor is controlled through the `smd.red` library, which allows sending commands to the motor via the Red controller.
   2. A `Master` object is used to establish communication with the motor, and the motor is attached using the `Red(ID)` method.
3. **Motor Speed Configuration**:
   1. The program allows the user to input a speed value (in RPM or another suitable unit). The motor's velocity is set to this value using the `m.set_velocity()` method.
   2. The motor's other parameters, such as the revolutions per minute (RPM) and control settings, are preconfigured for optimal operation.
4. **User Input**:
   1. The program prompts the user to input the desired motor speed, and then it sets the motor’s velocity accordingly. The speed is used to control how fast the motor will rotate.
5. **Feedback to User**:
   1. After setting the motor speed, the program confirms the set speed with a printed message: `"The engine rotates at speed {speed}."`

## **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) or [Arduino Gateway Module](https://acrome.gitbook.io/acrome-smd-docs/electronics/gateway-modules/arduino-gateway-module).
   * Connect the 100 RPM [BDC Motor](/electronics/electrical-motors/brushed-dc-motors-bdc.md) with Encoder to the motor ports of 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/CEd0OerPHKnH3zf1gLMZ" alt=""><figcaption></figcaption></figure>

## Step 3: Run & Test

#### Run the Script

1\. Upload the Arduino code to the SMD Master Controller using the Arduino IDE.

2\. Open the Serial Monitor (set baud rate to 115200).

3\. Enter a speed value (0 to 5000) to adjust the motor speed.

#### Experience Speed Control

• Observe how the motor starts at 50 RPM (default) and adjusts based on the entered speed.

• Enter a higher speed value to increase the motor velocity.

• Enter zero (0) to stop the motor.

## Codes

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

```python
from smd.red import *  # Import the SMD Red motor control library
from serial.tools.list_ports import comports  # Import serial communication tools
from platform import system  # Import system information module
import math
import os

# Function to detect and return the correct USB port for communication
def USB_Port():
    ports = list(comports())  # Get a list of available serial ports
    usb_names = {
        "Windows": ["USB Serial Port"],  # Windows-specific port names
        "Linux": ["/dev/ttyUSB"],  # Linux-specific port names
        "Darwin": [  # macOS-specific port names
            "/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()  # Detect the operating system
    if ports:  # If ports are available
        for port, desc, hwid in sorted(ports):  # Iterate through detected ports
            # Check if the port name or description matches the expected USB names
            if any(name in port or name in desc for name in usb_names.get(os_name, [])):
                return port  # Return the detected port
        
        # If no matching port was found, print the available ports
        print("Current ports:")
        for port, desc, hwid in ports:
            print(f"Port: {port}, Description: {desc}, Hardware ID: {hwid}")
    else:
        print("No port found")  # Print message if no ports are detected
    return None  # Return None if no suitable port is found

# Get the detected USB port
port = USB_Port()

# Initialize the motor controller using the detected port
m = Master(port)

# Define motor ID
ID = 0

# Attach the motor to the master controller
m.attach(Red(ID))

# Configure motor settings
m.set_shaft_cpr(ID, 6533)  # Set encoder counts per revolution (CPR)
m.set_shaft_rpm(ID, 100)  # Set shaft rotation speed in RPM
m.set_operation_mode(ID, OperationMode.Velocity)  # Set motor to velocity control mode
m.set_control_parameters_velocity(ID, 30.0, 5.0, 0.0)  # Set PID control parameters (P, I, D)
m.enable_torque(ID, True)  # Enable motor torque

# Get user input for speed
speed = input("Speed: ")

# Set the velocity of the motor based on user input
m.set_velocity(ID, float(speed))

# Print the motor's current speed
print("The motor rotates at speed " + speed + ".")
```

{% endcode %}
{% endtab %}

{% tab title="Arduino Code" %}

```cpp
#include <Acrome-SMD.h>  // Include the Acrome-SMD library

#define ID         0  // Define motor ID
#define CPR        6533  // Encoder counts per revolution
#define RPM        100  // Shaft speed in RPM
#define BAUDRATE   115200  // Baud rate for serial communication

Red master(ID, Serial, BAUDRATE);  // Initialize the motor controller

void setup() {
    Serial.begin(BAUDRATE);  // Start Serial Monitor
    delay(500);  // Wait to stabilize serial communication

    master.begin();  // Initialize SMD motor communication

    Serial.println("Detecting SMD motor...");
    
    // Set motor settings
    master.setMotorCPR(CPR);  // Set encoder CPR
    master.setMotorRPM(RPM);  // Set motor RPM
    master.setOperationMode(2);  // Set motor to velocity control mode (2 = Velocity Mode)
    
    // Set PID control parameters: (OperationMode, P, I, D, Deadband, Feedforward)
    master.setControlParameters(2, 30.0, 5.0, 0.0, 0.0, 0.0);
    
    // Enable motor torque
    master.torqueEnable(1);

    Serial.println("Motor is ready.");
}

void loop() {
    Serial.println("Enter the speed:");

    // Wait for user input
    while (Serial.available() == 0) {
        delay(100);
    }

    // Read input speed from Serial Monitor
    int speed = Serial.parseInt();
    Serial.println("Speed entered: " + String(speed));

    // Set motor speed
    master.setpoint(2, speed);

    // Print confirmation message
    Serial.println("The motor rotates at speed " + String(speed) + ".");
    
    delay(100);  // Small delay to avoid overloading the system
}
```

{% 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-speed-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.
