Basic Motor Position Control Application

In this application, you will learn how to control a DC motor’s exact position in degrees using the Position Mode of the SMD Red module. You will enter a target angle between 0 and 360, and the motor will rotate precisely to that point using encoder feedback.

About Tools and Materials:

SMD Red (Purchase Here)

SMD USB Gateway (Purchase Here)

Arduino Gateway Module (Purchase Here)

BDC Motor (Purchase Here)

Step 1: Hardware & Software Overview

Project Key Components

  1. SMD Red: Controls the brushed DC motor and reads encoder feedback for accurate position control.

  2. BDC Motor: Converts electrical energy to mechanical rotation and provides position feedback via encoder signals.

Project Key Features

  1. Precise angle-based control: Move the motor shaft to an exact angle between 0° and 360°.

  2. Real-time encoder feedback: Monitor actual shaft position with high-resolution encoder data.

  3. Tunable PID position control: Customize responsiveness and stability using: set_control_parameters_position

  4. Encoder-integrated control loop: Closed-loop control ensures accurate positioning over time.

Step 2: Assemble

Getting Started

Hardware Setup

Project Wiring Diagram

Step 3: Run & Test

Run the Script

After launching the script, you will be prompted to enter a desired angle between 0 and 360 degrees. The motor will rotate to the target position using encoder feedback and stop.

Codes

from smd.red import *  # Import SMD Red control library
from serial.tools.list_ports import comports  # For listing available serial ports
from platform import system  # To detect the operating system
import time  # For sleep/delay
import math  # For mathematical operations

# Automatically detect and return the correct USB port connected to SMD Red
def USB_Port():
    ports = list(comports())
    usb_names = {
        "Windows": ["USB Serial Port"],
        "Linux": ["/dev/ttyUSB"],
        "Darwin": ["/dev/cu."]  # macOS ports usually start with /dev/cu.
    }
    os_name = system()
    for port, desc, _ in ports:
        if any(name in port or name in desc for name in usb_names.get(os_name, [])):
            return port
    return None

def main():
    port = USB_Port()
    if not port:
        print("No port found.")  # If no port is found, exit the program
        return

    master = Master(port)  # Create a Master object to control SMD Red
    motor_id = 1  # ID of the connected motor
    CPR = 6533  # Encoder Counts Per Revolution

    # Attach the motor and configure its basic parameters
    master.attach(Red(motor_id))
    master.set_shaft_cpr(motor_id, CPR)  # Set encoder resolution
    master.set_shaft_rpm(motor_id, 100)  # Set nominal RPM
    master.set_control_parameters_position(motor_id, 0.5, 0.0, 20.0)  # Set PID gains for position control
    master.set_operation_mode(motor_id, OperationMode.Position)  # Enable position control mode
    master.enable_torque(motor_id, True)  # Enable torque so the motor can move

    while True:
        try:
            # Get target angle from user input and keep it in [0, 360) range
            angle = float(input("Enter target angle (0-360°): ")) % 360

            # Convert angle in degrees to encoder counts
            target = angle * (CPR / 360)

            # Send position command to the motor
            master.set_position(motor_id, target)

            # Wait for movement to complete
            time.sleep(0.5)

            # Read actual encoder position
            current = master.get_position(motor_id)

            # Convert encoder counts back to degrees
            actual = current * (360 / CPR)

            # Print both target and actual angles
            print(f"Target: {angle:.2f}°, Actual: {actual:.2f}°\n")

        except KeyboardInterrupt:
            # On user interrupt (Ctrl+C), disable torque and stop the motor
            master.enable_torque(motor_id, False)
            break

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

Last updated