rahul Rajan
rahul Rajan

Reputation: 1

Unable to Communicate with Phytron MCC-1 W-USB Controller via Raspberry Pi Using Python Serial Interface

I'm trying to control a Phytron ZSH 57/2 stepper motor using an MCC-1 W-USB controller connected to a Raspberry Pi 5 via a USB Type B connection. I'm using a Python script with the pyserial library to send commands over the serial interface, but I keep receiving no response from the MCC-1 controller.

Setup Details:

Issue:

Troubleshooting Steps So Far:

  1. Checked Wiring: All wiring is double-checked and securely connected.

  2. Proper GND: Connected the GND pin of the Raspberry Pi to the GND terminal on the MCC-1 to ensure proper grounding.

  3. Set R/L Switch: The R/L switch on the MCC-1 is set to R (Remote).

  4. Address Dial: Set the address dial to match the address in the Python code ('0').

  5. Permissions: Added my user to the dialout group to ensure serial port access.

  6. Minicom Settings: Configured minicom with baud rate 57600, 8N1, no flow control. It shows as offline.

Questions:

  1. Is there anything else I need to do to establish proper communication between the Raspberry Pi and the MCC-1 W-USB controller?

  2. Are there specific steps beyond the manual required for proper USB communication with the MCC-1?

  3. Am I structuring my command correctly with <STX> and <ETX>? The manual mentions a data format, but I'm not sure if the Python code is fully compliant.

  4. Could there be a driver or firmware update needed for the MCC-1 to work properly with Raspberry Pi over USB?

Any help would be appreciated. Thanks in advance!

import serial
import time

MCC_PORT = '/dev/ttyUSB0'  # Adjust as per your connection
BAUD_RATE = 57600  # Usually default, adjust if needed

try:
    ser = serial.Serial(MCC_PORT, BAUD_RATE, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=5, rtscts=False)
    if ser.is_open:
        print(f"Serial port {MCC_PORT} opened successfully.")
    else:
        print(f"Failed to open serial port {MCC_PORT}.")
except serial.SerialException as e:
    print(f"Error opening serial port: {e}")
    exit(1)


def calculate_checksum(command):
    checksum = 0
    for byte in command:
        checksum ^= ord(byte)
    return f"{checksum:02X}"  # Return the checksum as a two-character hex string

def send_command(address, command, use_checksum=False, retries=3):
    try:
        if use_checksum:
            checksum = calculate_checksum(f"{address}{command}")
            full_command = f"\x02{address}{command}{checksum}\x03"
        else:
            full_command = f"\x02{address}{command}\x03"
        
        for attempt in range(retries):
            ser.write(full_command.encode())
            print(f"Sent command: {full_command}")  # Debug message
            time.sleep(2)  # Allow more time for the motor to react
            response = ser.readline().decode().strip()
            if response:
                if response == '\x06':  # ACK
                    print("Command acknowledged.")
                    return True
                elif response == '\x15':  # NAK
                    print("Command not acknowledged. Retrying...")
                else:
                    print(f"Unexpected response: {response}")
                    return False
            else:
                print("No response from MCC driver. Retrying...")
        print("Failed to get a response after multiple attempts.")
    except Exception as e:
        print(f"Error sending command: {e}")
    return False

# Function to initialize motor controller
def initialize_motor(address):
    """
    Initializes the motor by setting up necessary parameters and performing a reference search run.
    """
    # Test communication with a simple status command
    if not send_command(address, "ST"):
        print("Failed to communicate with MCC driver. Check connections and settings.")
        return False

    # Set P17 Boost Current to 1 (Enable boost during motor run)
    if not send_command(address, "XP17S1"):
        return False

    # Set P41 Run Current and P42 Boost Current
    if not send_command(address, "XP41S50"):  # Example value, adjust as needed
        return False
    if not send_command(address, "XP42S70"):  # Example value, adjust as needed
        return False

    # Set P45 Step Resolution (example: full step)
    if not send_command(address, "XP45S1"):
        return False

    # Set P46 Current Shaping to 1 (Activate Current Shaping)
    if not send_command(address, "XP46S1"):
        return False

    # Perform Reference Search Run
    if not send_command(address, "X0+"):
        return False

    # Activate Power Stage
    if not send_command(address, "XMA"):
        return False
    
    # Set R/L Switch to Remote (handled physically on MCC-1)
    print("Ensure the R/L switch is set to 'R' (Remote) for external control.")
    
    # Check Address Setting (address dial should match address used in code)
    print(f"Ensure the address dial on the MCC-1 matches the address '{address}' used in the code.")

    # Simulate Limit Switches if not in use (X2/X1 should be bridged if not connected)
    print("If limit switches are not connected, bridge the X2/X1 terminals to simulate active switches.")

    print("Motor initialized successfully.")
    return True

# Function to control motor
def control_motor(address, direction, speed, action):
    """
    address: Address of the MCC controller ('0'-'9', 'A'-'F')
    direction: 'CW' or 'CCW'
    speed: in RPM
    action: 'start' or 'stop'
    """
    if direction.upper() == 'CW':
        if not send_command(address, "MA+"):
            return  # Exit if command fails
    elif direction.upper() == 'CCW':
        if not send_command(address, "MA-"):
            return  # Exit if command fails
    else:
        print("Invalid direction. Use 'CW' or 'CCW'.")
        return

    if not send_command(address, f"V{speed}"):
        return  # Exit if command fails

    if action.lower() == 'start':
        send_command(address, "S")  # Start rotation
    elif action.lower() == 'stop':
        send_command(address, "E")  # Stop rotation
    else:
        print("Invalid action. Use 'start' or 'stop'.")

# Example usage
try:
    # Initialize the motor
    if initialize_motor('0'):
        # Rotate Clockwise at 30 RPM and start
        control_motor('0', 'CW', 30, 'start')

        # Run motor for 5 seconds
        time.sleep(5)

        # Stop motor
        control_motor('0', 'CW', 30, 'stop')

except KeyboardInterrupt:
    # Handle the interrupt and stop motor safely
    control_motor('0', 'CW', 30, 'stop')

finally:
    # Close serial port
    ser.close()


        send_command("\x02E\x03")  # Stop rotation
    else:
        print("Invalid action. Use 'start' or 'stop'.")

# Example usage
try:
    # Rotate Clockwise at 30 RPM and start
    control_motor('CW', 30, 'start')

    # Run motor for 5 seconds
    time.sleep(5)

    # Stop motor
    control_motor('CW', 30, 'stop')

except KeyboardInterrupt:
    # Handle the interrupt and stop motor safely
    control_motor('CW', 30, 'stop')

finally:
    # Close serial port
    ser.close()

Upvotes: 0

Views: 15

Answers (0)

Related Questions