Reputation: 1
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.
Controller: MCC-1 W-USB
Motor: Phytron ZSH 57/2
Microcontroller: Raspberry Pi 5
Connection: USB Type A to Type B cable between Raspberry Pi and MCC-1 (X5 Com port).
Serial Settings:
Baud rate: 57600
Data bits: 8
Parity: None
Stop bits: 1
Timeout: 2 seconds
When I run this code, I consistently get "No response from MCC driver."
I also tried running minicom to manually test communication, but it says the device is offline and I receive no response when typing commands.
Checked Wiring: All wiring is double-checked and securely connected.
Proper GND: Connected the GND pin of the Raspberry Pi to the GND terminal on the MCC-1 to ensure proper grounding.
Set R/L Switch: The R/L switch on the MCC-1 is set to R (Remote).
Address Dial: Set the address dial to match the address in the Python code ('0'
).
Permissions: Added my user to the dialout group to ensure serial port access.
Minicom Settings: Configured minicom with baud rate 57600, 8N1, no flow control. It shows as offline.
Is there anything else I need to do to establish proper communication between the Raspberry Pi and the MCC-1 W-USB controller?
Are there specific steps beyond the manual required for proper USB communication with the MCC-1?
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.
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